型のバインド リファレンス ガイド
このドキュメントでは、API コントラクト ファイルに注釈を付けてバインディングと生成されたコードを駆動するために使用できる属性の一覧について説明します
Xamarin.iOS および Xamarin.Mac API コントラクトは、ほとんどの場合、C# で Objective-C コードを C# に表わす方法を定義するインターフェイス定義として記述されます。 このプロセスには、インターフェイス宣言と、API コントラクトで必要となる基本的な型定義の組み合わせが含まれます。 バインドの種類の概要については、コンパニオン ガイド「Objective-Cライブラリのバインド」を参照してください。
型定義
構文:
[BaseType (typeof (BTYPE))
interface MyType : [Protocol1, Protocol2] {
IntPtr Constructor (string foo);
}
[BaseType]
属性を持つコントラクト定義内のすべてのインターフェイスは、生成されたオブジェクトの基本データ型を宣言します。 上記の宣言では、Objective-C 型 (MyType
と呼ばれる) にバインドされる MyType
クラス C# 型が生成されます。
インターフェイス継承構文を使用して typename (上記のサンプルの Protocol1
と Protocol2
) の後に任意の型を指定した場合、それらのインターフェイスのコンテンツは、MyType
のコントラクトの一部であるかのようにインライン化されます。
型がプロトコルを採用する Xamarin.iOS が表す方法は、すべてのメソッドをインライン化し、プロトコル内でその型自体に宣言されるプロパティによって行われます。
次に、UITextField
の Objective-C 宣言が Xamarin.iOS コントラクトで定義される方法を示します。
@interface UITextField : UIControl <UITextInput> {
}
次のように C# API コントラクトとして記述します。
[BaseType (typeof (UIControl))]
interface UITextField : UITextInput {
}
インターフェイスに他の属性を適用し、[BaseType]
属性を構成することで、コード生成の他の多くの側面を制御できます。
イベントの生成
Xamarin.iOS と Xamarin.Mac API 設計の 1 つの機能は、Objective-C デリゲート クラスを C# イベントとコールバックとしてマップすることです。 ユーザーは、インスタンスごとに Objective-C プログラミング パターンを採用するかどうかを選択できます。これは、Objective-C ランタイムが呼び出すさまざまなメソッドを実装するクラスの Delegate
インスタンスなどのプロパティに割り当てるか、C# スタイルのイベントとプロパティを選択することで行えます。
Objective-C モデルの使用方法の例を 1 つ見てみましょう。
bool MakeDecision ()
{
return true;
}
void Setup ()
{
var scrollView = new UIScrollView (myRect);
scrollView.Delegate = new MyScrollViewDelegate ();
...
}
class MyScrollViewDelegate : UIScrollViewDelegate {
public override void Scrolled (UIScrollView scrollView)
{
Console.WriteLine ("Scrolled");
}
public override bool ShouldScrollToTop (UIScrollView scrollView)
{
return MakeDecision ();
}
}
上の例では、2 つのメソッドを上書きすることを選択していることがわかります。1 つはスクロール イベントが発生したことを示す通知で、もう 1 つは、scrollView
に対して先頭にスクロールするかどうかを示すブール値を返すように指示するコールバックです。
C# モデルを使用すると、ライブラリのユーザーは、C# イベント構文またはプロパティ構文を使用して通知をリッスンし、値を返す必要があるコールバックをフックできます。
同じ機能の C# コードは、ラムダの使用のようになります。
void Setup ()
{
var scrollview = new UIScrollView (myRect);
// Event connection, use += and multiple events can be connected
scrollView.Scrolled += (sender, eventArgs) { Console.WriteLine ("Scrolled"); }
// Property connection, use = only a single callback can be used
scrollView.ShouldScrollToTop = (sv) => MakeDecision ();
}
イベントは値を返さない (void 戻り値の型を持つ) ため、複数のコピーを接続できます。 ShouldScrollToTop
はイベントでなく、このシグネチャを持つ型 UIScrollViewCondition
を持つプロパティです。
public delegate bool UIScrollViewCondition (UIScrollView scrollView);
これは bool
値を返します。この場合、ラムダ構文を使用すると、MakeDecision
関数からこの値のみを返せます。
バインディング ジェネレーターは、UIScrollView
などのクラスをその UIScrollViewDelegate
とリンクするイベントとプロパティの生成をサポートします (これらの Model クラスを適切に呼び出します)。これは、[BaseType]
定義に Events
パラメーターと Delegates
パラメーター (後述) を使用して注釈を付けることで行われます。
[BaseType]
にこれらのパラメーターで注釈を付けるだけでなく、いくつかのコンポーネントをジェネレーターに通知する必要があります。
複数のパラメーターを受け取るイベント (Objective-C では、この規則はデリゲート クラスの最初のパラメーターが送信者オブジェクトのインスタンスであること) の場合は、生成される EventArgs
クラスに付ける名前を指定する必要があります。 これは、Model クラスのメソッド宣言の [EventArgs]
属性を使用して行われます。 次に例を示します。
[BaseType (typeof (UINavigationControllerDelegate))]
[Model][Protocol]
public interface UIImagePickerControllerDelegate {
[Export ("imagePickerController:didFinishPickingImage:editingInfo:"), EventArgs ("UIImagePickerImagePicked")]
void FinishedPickingImage (UIImagePickerController picker, UIImage image, NSDictionary editingInfo);
}
上記の宣言では、EventArgs
から派生し、UIImage
パラメーターと NSDictionary
パラメーターの両をパックする UIImagePickerImagePickedEventArgs
クラスが生成されます。 ジェネレーターによって次の結果が生成されます。
public partial class UIImagePickerImagePickedEventArgs : EventArgs {
public UIImagePickerImagePickedEventArgs (UIImage image, NSDictionary editingInfo);
public UIImage Image { get; set; }
public NSDictionary EditingInfo { get; set; }
}
その後、UIImagePickerController
クラスで次が公開されます。
public event EventHandler<UIImagePickerImagePickedEventArgs> FinishedPickingImage { add; remove; }
値を返すモデル メソッドのバインド方法は異なります。 これらには、生成された C# デリゲートの名前 (メソッドのシグネチャ) と、ユーザーが実装を提供しない場合に返す既定値の両方が必要です。
たとえば、ShouldScrollToTop
定義は次のようになります。
[BaseType (typeof (NSObject))]
[Model][Protocol]
public interface UIScrollViewDelegate {
[Export ("scrollViewShouldScrollToTop:"), DelegateName ("UIScrollViewCondition"), DefaultValue ("true")]
bool ShouldScrollToTop (UIScrollView scrollView);
}
上記では、上に示したシグネチャを持つ UIScrollViewCondition
デリゲートが作成され、ユーザーが実装を提供しない場合、戻り値は true になります。
[DefaultValue]
属性に加えて、呼び出しで指定されたパラメーターの値を返すようにジェネレーターに指示する [DefaultValueFromArgument]
属性、または既定値がないことをジェネレーターに指示する [NoDefaultValue]
パラメーターを使用することもできます。
BaseTypeAttribute
構文:
public class BaseTypeAttribute : Attribute {
public BaseTypeAttribute (Type t);
// Properties
public Type BaseType { get; set; }
public string Name { get; set; }
public Type [] Events { get; set; }
public string [] Delegates { get; set; }
public string KeepRefUntil { get; set; }
}
BaseType.Name
この Name
プロパティを使用して、この型が Objective-C ワールド内でバインドする名前を制御します。 これは通常、C# 型に .NET Framework デザイン ガイドラインに準拠している名前を付けるために使用されますが、その規則に従わない Objective-C の名前にマップされます。
たとえば、次の場合、.NET Framework デザイン ガイドラインでは "URL" でなく "Url" が使用されるため、Objective-CNSURLConnection
型を NSUrlConnection
にマップします。
[BaseType (typeof (NSObject), Name="NSURLConnection")]
interface NSUrlConnection {
}
指定した名前は、バインディングで生成された [Register]
属性の値として使用されます。 Name
を指定しない場合は、生成された出力の [Register]
属性の値として、型の短い名前が使用されます。
BaseType.Events と BaseType.Delegates
これらのプロパティは、生成されたクラスで C# スタイルのイベントの生成を促進するために使用されます。 これらは、特定のクラスとその Objective-C デリゲート クラスをリンクするために使用されます。 多くの場合、クラスがデリゲート クラスを使用して通知とイベントを送信します。 たとえば、BarcodeScanner
はコンパニオン BardodeScannerDelegate
クラスを持ちます。 BarcodeScanner
クラスには通常 BarcodeScannerDelegate
のインスタンスを割り当てる Delegate
プロパティを持ち、これは機能するものの、C# のようなスタイルのイベント インターフェイスをユーザーに公開する場合があり、そのような場合は、[BaseType]
属性の Events
プロパティと Delegates
プロパティを使用します。
これらのプロパティは常に一緒に設定され、同じ数の要素を持ち、同期を保つ必要があります。この Delegates
配列には、ラップする弱く型指定されたデリゲートごとに 1 つの文字列が含まれ、Events
配列には、関連付ける型ごとに 1 つの型が含まれます。
[BaseType (typeof (NSObject),
Delegates=new string [] { "WeakDelegate" },
Events=new Type [] {typeof(UIAccelerometerDelegate)})]
public interface UIAccelerometer {
}
[BaseType (typeof (NSObject))]
[Model][Protocol]
public interface UIAccelerometerDelegate {
}
BaseType.KeepRefUntil
このクラスの新しいインスタンスの作成時にこの属性を適用すると、そのオブジェクトのインスタンスは、KeepRefUntil
によって参照されるメソッドが呼び出されるまで保持されます。 これは、ユーザーがコードを使用するためにオブジェクトへの参照を保持しないようにする場合に、API の使いやすさを向上させるために役立ちます。 このプロパティの値は Delegate
クラス内のメソッドの名前であるため、これを Events
プロパティと Delegates
プロパティとも組み合わせて使用する必要があります。
次の例は、Xamarin.iOS で UIActionSheet
がこれを使用する方法を示しています。
[BaseType (typeof (NSObject), KeepRefUntil="Dismissed")]
[BaseType (typeof (UIView),
KeepRefUntil="Dismissed",
Delegates=new string [] { "WeakDelegate" },
Events=new Type [] {typeof(UIActionSheetDelegate)})]
public interface UIActionSheet {
}
[BaseType (typeof (NSObject))]
[Model][Protocol]
public interface UIActionSheetDelegate {
[Export ("actionSheet:didDismissWithButtonIndex:"), EventArgs ("UIButton")]
void Dismissed (UIActionSheet actionSheet, nint buttonIndex);
}
DesignatedDefaultCtorAttribute
この属性がインターフェイス定義に適用されると、init
セレクターにマップされる既定の (生成された) コンストラクターに [DesignatedInitializer]
属性が生成されます。
DisableDefaultCtorAttribute
この属性がインターフェイス定義に適用されると、ジェネレーターが既定のコンストラクターを生成できなくなります。
この属性は、クラス内の他のコンストラクターのいずれかでオブジェクトを初期化する必要がある場合に使用します。
PrivateDefaultCtorAttribute
この属性がインターフェイス定義に適用されると、既定のコンストラクターにプライベートとしてフラグが設定されます。 つまり、拡張ファイルからこのクラスのオブジェクトを内部的にインスタンス化することはできますが、クラスのユーザーはアクセスできません。
CategoryAttribute
型定義でこの属性を使用して、Objective-C カテゴリをバインドし、それらを C# 拡張メソッドとして公開し、Objective-C がこの機能を公開する方法をミラー化します。
カテゴリは、クラスで使用できる一連のメソッドとプロパティを拡張するために使用される Objective-C メカニズムです。 実際には、特定のフレームワークがリンクされている場合 (たとえば UIKit
) に基底クラス (たとえば NSObject
) の機能を拡張するか、それらのメソッドを使用できるようにするかのいずれかに使用されますが、新しいフレームワークがリンクされている場合にのみです。 また、クラス内の特徴を機能別に整理するために使用される場合もあります。 これらは、C# 拡張メソッドに似ています。
Objective-C のカテゴリは次のようになります。
@interface UIView (MyUIViewExtension)
-(void) makeBackgroundRed;
@end
上記の例は、UIView
のインスタンスを makeBackgroundRed
メソッドで拡張するライブラリにあります。
それらをバインドするには、インターフェイス定義で [Category]
属性を使用できます。 [Category]
属性を使用する場合、[BaseType]
属性の意味は、拡張する基底クラスを指定するために使用されることから、拡張する型に変わります。
UIView
拡張機能がバインドされ、C# 拡張メソッドに変換される方法を次に示します。
[BaseType (typeof (UIView))]
[Category]
interface MyUIViewExtension {
[Export ("makeBackgroundRed")]
void MakeBackgroundRed ();
}
上記では、MakeBackgroundRed
拡張メソッドを含むクラス MyUIViewExtension
が作成されます。 これは、MakeBackgroundRed
を任意の UIView
サブクラスで呼び出して、Objective-C で取得するのと同じ機能が得られるようになったことを意味します。
場合によっては、次の例のように、カテゴリ内に静的メンバーがあります。
@interface FooObject (MyFooObjectExtension)
+ (BOOL)boolMethod:(NSRange *)range;
@end
これにより、カテゴリ C# インターフェイス定義が正しくなくなります。
[Category]
[BaseType (typeof (FooObject))]
interface FooObject_Extensions {
// Incorrect Interface definition
[Static]
[Export ("boolMethod:")]
bool BoolMethod (NSRange range);
}
これは、FooObject
インスタンスが必要な BoolMethod
拡張機能を使用するために、ObjC 静的拡張をバインドしているため正しくありません。これは、C# 拡張メソッドの実装方法に起因する副作用です。
上記の定義を使用する唯一の方法は、次のやっかいなコードです。
(null as FooObject).BoolMethod (range);
これを回避するための推奨事項は、FooObject
インターフェイス定義自体内の BoolMethod
定義をインライン化することです。これにより、意図した FooObject.BoolMethod (range)
のようにこの拡張機能を呼び出せるようになります。
[BaseType (typeof (NSObject))]
interface FooObject {
[Static]
[Export ("boolMethod:")]
bool BoolMethod (NSRange range);
}
[Category]
定義内で [Static]
メンバーが見つかるたびに警告 (BI1117) を発行します。 [Category]
定義内に [Static]
メンバーを本当に含める場合は、[Category (allowStaticMembers: true)]
を使用するか、メンバーまたは [Category]
インターフェイス定義を [Internal]
で修飾することで、警告を無音にできます。
StaticAttribute
この属性をクラスに適用すると、静的クラス (NSObject
から派生していない静的クラス) が生成されるため、[BaseType]
属性は無視されます。 静的クラスは、公開する C パブリック変数をホストするために使用されます。
次に例を示します。
[Static]
interface CBAdvertisement {
[Field ("CBAdvertisementDataServiceUUIDsKey")]
NSString DataServiceUUIDsKey { get; }
次の API を使用して C# クラスを生成します。
public partial class CBAdvertisement {
public static NSString DataServiceUUIDsKey { get; }
}
プロトコルまたはモデルの定義
モデルは通常、プロトコルの実装で使用されます。 これらは、実際に上書きされたメソッド Objective-C にのみランタイムが登録される点が異なります。 それ以外の場合、メソッドは登録されません。
これは一般に、ModelAttribute
を使用してフラグが設定されたクラスをサブクラス化する場合、基本メソッドを呼び出すべきでないことを意味します。 そのメソッドを呼び出すと、Foundation.You_Should_Not_Call_base_In_This_Method という例外がスローされます。 オーバーライドするすべてのメソッドに対してサブクラスに動作全体を実装する必要があります。
AbstractAttribute
既定では、プロトコルの一部であるメンバーは必須ではありません。 これにより、ユーザーは C# のクラスから派生させ、対象のメソッドのみをオーバーライドするだけで、Model
オブジェクトのサブクラスを作成できます。 Objective-C コントラクトでは、ユーザーがこのメソッドの実装を提供する必要がある場合があります (これらは Objective-C 内の @required
ディレクティブでフラグが設定されます)。 このような場合は、[Abstract]
属性を使用してこれらのメソッドにフラグを設定する必要があります。
[Abstract]
属性は、メソッドまたはプロパティに適用でき、これにより、ジェネレーターは生成されたメンバーに抽象としてフラグを設定し、クラスを抽象クラスに設定します。
Xamarin.iOS から取得した内容を次に示します。
[BaseType (typeof (NSObject))]
[Model][Protocol]
public interface UITableViewDataSource {
[Export ("tableView:numberOfRowsInSection:")]
[Abstract]
nint RowsInSection (UITableView tableView, nint section);
}
DefaultValueAttribute
ユーザーが Model オブジェクト内のこの特定のメソッドのメソッドを指定しない場合に、モデル メソッドによって返される既定値を指定します
構文:
public class DefaultValueAttribute : Attribute {
public DefaultValueAttribute (object o);
public object Default { get; set; }
}
たとえば、Camera
クラスの次の虚数デリゲート クラスでは、Camera
クラスのプロパティとして公開される ShouldUploadToServer
を提供します。 Camera
クラスのユーザーが、true または false を応答できるラムダに値を明示的に設定しない場合、返される既定値は、DefaultValue
属性で指定した値である false になります。
[BaseType (typeof (NSObject))]
[Model][Protocol]
interface CameraDelegate {
[Export ("camera:shouldPromptForAction:"), DefaultValue (false)]
bool ShouldUploadToServer (Camera camera, CameraAction action);
}
ユーザーが虚数クラスでハンドラーを設定した場合、この値は無視されます。
var camera = new Camera ();
camera.ShouldUploadToServer = (camera, action) => return SomeDecision ();
関連項目: [NoDefaultValue]
、[DefaultValueFromArgument]
。
DefaultValueFromArgumentAttribute
構文:
public class DefaultValueFromArgumentAttribute : Attribute {
public DefaultValueFromArgumentAttribute (string argument);
public string Argument { get; }
}
この属性は、Model クラスの値を返すメソッドで指定されると、ユーザーが独自のメソッドまたはラムダを指定しなかった場合に、指定されたパラメーターの値を返すようにジェネレーターに指示します。
例:
[BaseType (typeof (NSObject))]
[Model][Protocol]
public interface NSAnimationDelegate {
[Export ("animation:valueForProgress:"), DelegateName ("NSAnimationProgress"), DefaultValueFromArgumentAttribute ("progress")]
float ComputeAnimationCurve (NSAnimation animation, nfloat progress);
}
上記の場合、NSAnimation
クラスのユーザーが C# のイベント/プロパティのいずれかを使用することを選択し、NSAnimation.ComputeAnimationCurve
をメソッドまたはラムダに設定しなかった場合、戻り値は progress パラメーターで渡された値になります。
関連項目: [NoDefaultValue]
、[DefaultValue]
IgnoredInDelegateAttribute
Model クラスからホスト クラスにイベントまたはデリゲート プロパティを公開しないことが適切な場合もあるため、この属性を追加することで、ジェネレーターで修飾されたメソッドが生成されないように指示します。
[BaseType (typeof (UINavigationControllerDelegate))]
[Model][Protocol]
public interface UIImagePickerControllerDelegate {
[Export ("imagePickerController:didFinishPickingImage:editingInfo:"), EventArgs ("UIImagePickerImagePicked")]
void FinishedPickingImage (UIImagePickerController picker, UIImage image, NSDictionary editingInfo);
[Export ("imagePickerController:didFinishPickingImage:"), IgnoredInDelegate)] // No event generated for this method
void FinishedPickingImage (UIImagePickerController picker, UIImage image);
}
DelegateNameAttribute
この属性は、使用するデリゲート シグネチャの名前を設定する値を返す Model メソッドで使用されます。
例:
[BaseType (typeof (NSObject))]
[Model][Protocol]
public interface NSAnimationDelegate {
[Export ("animation:valueForProgress:"), DelegateName ("NSAnimationProgress"), DefaultValueFromArgumentAttribute ("progress")]
float ComputeAnimationCurve (NSAnimation animation, float progress);
}
上記の定義では、ジェネレーターは次のパブリック宣言を生成します。
public delegate float NSAnimationProgress (MonoMac.AppKit.NSAnimation animation, float progress);
DelegateApiNameAttribute
この属性は、ジェネレーターがホスト クラスで生成されたプロパティの名前を変更できるようにするために使用されます。 FooDelegate クラス メソッドの名前が Delegate クラスにとって適切な場合は有効ですが、ホスト クラスではプロパティとして不適切に見える場合もあります。
FooDelegate クラスの名前をそのまま維持するのが適切なオーバーロード メソッドが 2 つ以上ある場合は有効であり、そうする必要がありますが、より適切な名前でホスト クラスで公開する必要がある場合もあります。
例:
[BaseType (typeof (NSObject))]
[Model][Protocol]
public interface NSAnimationDelegate {
[Export ("animation:valueForProgress:"), DelegateApiName ("ComputeAnimationCurve"), DelegateName ("Func<NSAnimation, float, float>"), DefaultValueFromArgument ("progress")]
float GetValueForProgress (NSAnimation animation, float progress);
}
上記の定義では、ジェネレーターはホスト クラスで次のパブリック宣言を生成します。
public Func<NSAnimation, float, float> ComputeAnimationCurve { get; set; }
EventArgsAttribute
複数のパラメーターを受け取るイベント (Objective-C では、この規則はデリゲート クラスの最初のパラメーターが送信者オブジェクトのインスタンスであること) の場合は、生成される EventArgs クラスに付ける名前を指定する必要があります。 これは、Model
クラスのメソッド宣言の [EventArgs]
属性を使用して行われます。
次に例を示します。
[BaseType (typeof (UINavigationControllerDelegate))]
[Model][Protocol]
public interface UIImagePickerControllerDelegate {
[Export ("imagePickerController:didFinishPickingImage:editingInfo:"), EventArgs ("UIImagePickerImagePicked")]
void FinishedPickingImage (UIImagePickerController picker, UIImage image, NSDictionary editingInfo);
}
上記の宣言では、EventArgs から派生し、UIImage
パラメーターと NSDictionary
パラメーターの両をパックする UIImagePickerImagePickedEventArgs
クラスが生成されます。 ジェネレーターによって次の結果が生成されます。
public partial class UIImagePickerImagePickedEventArgs : EventArgs {
public UIImagePickerImagePickedEventArgs (UIImage image, NSDictionary editingInfo);
public UIImage Image { get; set; }
public NSDictionary EditingInfo { get; set; }
}
その後、UIImagePickerController
クラスで次が公開されます。
public event EventHandler<UIImagePickerImagePickedEventArgs> FinishedPickingImage { add; remove; }
EventNameAttribute
この属性は、ジェネレーターがクラスで生成されたイベントまたはプロパティの名前を変更できるようにするために使用されます。 モデル クラスに対して Model クラス メソッドの名前を付けるのが適切である場合は有効ですが、元のクラスではイベントまたはプロパティとして不適切に見える場合もあります。
たとえば、UIWebView
では、UIWebViewDelegate
から次のビットが使用されます。
[Export ("webViewDidFinishLoad:"), EventArgs ("UIWebView"), EventName ("LoadFinished")]
void LoadingFinished (UIWebView webView);
上記は LoadingFinished
を UIWebViewDelegate
のメソッドとして公開していますが、UIWebView
でフックするイベントとして公開されるのは LoadFinished
です。
var webView = new UIWebView (...);
webView.LoadFinished += delegate { Console.WriteLine ("done!"); }
ModelAttribute
コントラクト API の型定義に [Model]
属性を適用すると、ランタイムは、ユーザーがクラス内のメソッドを上書きした場合にのみ、クラス内のメソッドへの呼び出しを表示する特別なコードを生成します。 通常、この属性は、Objective-C デリゲート クラスをラップするすべての API に適用されます。
ランタイムは、対応するプロトコルの名前と一致する Objective-C クラスも生成します。
Objective-C クラスの名前は、次の 2 つの方法でカスタマイズできます。
AutoGeneratedName = true
の設定:[Model (AutoGeneratedName = true)]
これにより、ランタイムは Objective-C 型の一意の名前を生成します。 名前は現在、アセンブリ名とモデルの型の完全な名前に基づいています (これは将来変更される可能性があります)。
名前を明示的に指定します。
[Model (Name = "CustomName")]
AutoGeneratedName = true
を使用することをお勧めします。 .NET では、名前は常に生成され (上記の 2 のように明示的に指定されていない限り)、AutoGeneratedName
プロパティは存在しなくなります。
NoDefaultValueAttribute
モデルのメソッドが既定の戻り値を提供しないことを指定します。
これは、Objective-C ランタイムで、Objective-C ランタイム要求に false
を応答し、指定したセレクターがこのクラスに実装されているかどうかを判断することで動作します。
[BaseType (typeof (NSObject))]
[Model][Protocol]
interface CameraDelegate {
[Export ("shouldDisplayPopup"), NoDefaultValue]
bool ShouldUploadToServer ();
}
関連項目: [DefaultValue]
、[DefaultValueFromArgument]
プロトコル
Objective-C プロトコルの概念は、C# には実際には存在しません。 プロトコルは C# インターフェイスに似ていますが、プロトコルで宣言されているすべてのメソッドとプロパティを、それを採用するクラスで実装する必要があるわけではない点が異なります。 代わりに、一部のメソッドとプロパティは省略可能です。
一般的に、一部のプロトコルは Model クラスとして使用され、[Model]
属性を使用してバインドする必要があります。
[BaseType (typeof (NSObject))]
[Model, Protocol]
interface MyProtocol {
// Use [Abstract] when the method is defined in the @required section
// of the protocol definition in Objective-C
[Abstract]
[Export ("say:")]
void Say (string msg);
[Export ("listen")]
void Listen ();
}
Xamarin.iOS 7.0 以降では、新しく強化されたプロトコル バインド機能が組み込まれています。 [Protocol]
属性を含む定義では、実際には、プロトコルの使用方法を大幅に改善する 3 つのサポート クラスが生成されます。
// Full method implementation, contains all methods
class MyProtocol : IMyProtocol {
public void Say (string msg);
public void Listen (string msg);
}
// Interface that contains only the required methods
interface IMyProtocol: INativeObject, IDisposable {
[Export ("say:")]
void Say (string msg);
}
// Extension methods
static class IMyProtocol_Extensions {
public static void Optional (this IMyProtocol this, string msg);
}
}
クラスの実装では、個々のメソッドをオーバーライドして完全なタイプ セーフを取得できる完全な抽象クラスが提供されます。 ただし、C# では複数の継承がサポートされていないため、別の基底クラスが必要になる可能性があるものの、インターフェイスを実装する必要もあるシナリオがあります。
ここで、生成されたインターフェイス定義が使用されます。 これは、プロトコルから必要なすべてのメソッドを持つインターフェイスです。 これにより、プロトコルを実装する開発者は、そのインターフェイスを実装するだけ済みます。 ランタイムは、プロトコルを採用するように型を自動的に登録します。
インターフェイスは必要なメソッドのみを一覧表示し、省略可能なメソッドを公開することに注意してください。 つまり、プロトコルを採用するクラスは、必要なメソッドの完全な型チェックを受け取りますが、省略可能なプロトコル メソッドの弱い型指定 (Export 属性を使用して署名を手動で照合する) に頼る必要があります。
プロトコルを使用する API を使用しやすくするために、バインディング ツールでは、オプションのすべてのメソッドを公開する拡張メソッド クラスも生成されます。 つまり、API を使用している限り、プロトコルはすべてのメソッドを持つものとして扱えることを意味します。
API でプロトコル定義を使用する場合は、API 定義にスケルトンの空のインターフェイスを記述する必要があります。 API で MyProtocol を使用する場合は、次の操作を行う必要があります。
[BaseType (typeof (NSObject))]
[Model, Protocol]
interface MyProtocol {
// Use [Abstract] when the method is defined in the @required section
// of the protocol definition in Objective-C
[Abstract]
[Export ("say:")]
void Say (string msg);
[Export ("listen")]
void Listen ();
}
interface IMyProtocol {}
[BaseType (typeof(NSObject))]
interface MyTool {
[Export ("getProtocol")]
IMyProtocol GetProtocol ();
}
バインド時に IMyProtocol
が存在しないため、上記が必要です。これが、空のインターフェイスを指定する必要がある理由です。
プロトコルで生成されたインターフェイスの採用
プロトコル用に生成されたインターフェイスのいずれかを実装する場合は常に、次のようになります。
class MyDelegate : NSObject, IUITableViewDelegate {
nint IUITableViewDelegate.GetRowHeight (nint row) {
return 1;
}
}
必要なインターフェイス メソッドの実装は、適切な名前でエクスポートされるため、次のようになります。
class MyDelegate : NSObject, IUITableViewDelegate {
[Export ("getRowHeight:")]
nint IUITableViewDelegate.GetRowHeight (nint row) {
return 1;
}
}
これは、必要なすべてのプロトコル メンバーに対して機能しますが、省略可能なセレクターに注意する特別なケースがあります。
省略可能なプロトコル メンバーは、基底クラスを使用する場合と同じように扱われます。
public class UrlSessionDelegate : NSUrlSessionDownloadDelegate {
public override void DidWriteData (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite)
ただし、プロトコル インターフェイスを使用する場合は、[Export] を追加する必要があります。 オーバーライドから開始して追加すると、IDE によってオートコンプリートを介して追加されます。
public class UrlSessionDelegate : NSObject, INSUrlSessionDownloadDelegate {
[Export ("URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:")]
public void DidWriteData (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite)
実行時の 2 つの動作には若干の違いがあります。
- 基底クラス (例の NSUrlSessionDownloadDelegate) のユーザーは、必要なすべてのセレクターと省略可能なセレクターを提供し、適切な既定値を返します。
- インターフェイスのユーザー (例の INSUrlSessionDownloadDelegate) は、指定された正確なセレクターにのみ応答します。
ここでは、いくつかのまれなクラスの動作が異なる場合があります。 ただし、ほとんどの場合、どちらでも安全に使用できます。
プロトコルのインライン化
プロトコルの導入として宣言されている既存の Objective-C 型をバインドする場合は、プロトコルを直接インライン化する必要があります。 これを行うには、[BaseType]
属性を持たないインターフェイスとしてプロトコルを宣言し、インターフェイスの基本インターフェイスの一覧にプロトコルを一覧表示するだけです。
例:
interface SpeakProtocol {
[Export ("say:")]
void Say (string msg);
}
[BaseType (typeof (NSObject))]
interface Robot : SpeakProtocol {
[Export ("awake")]
bool Awake { get; set; }
}
メンバーの定義
このセクションの属性は、プロパティとメソッド宣言という型の個々のメンバーに適用されます。
AlignAttribute
プロパティの戻り値の型の配置値を指定するために使用します。 特定のプロパティは、特定の境界に揃えられる必要があるアドレスへのポインターを受け取ります (Xamarin.iOS では、これは、16 バイトに調整される必要がある一部の GLKBaseEffect
プロパティなどで発生します)。 このプロパティを使用してゲッターを装飾し、配置値を使用できます。 これは通常、Objective-C API と統合されている場合に、OpenTK.Vector4
型と OpenTK.Matrix4
型で使用されます。
例:
public interface GLKBaseEffect {
[Export ("constantColor")]
Vector4 ConstantColor { [Align (16)] get; set; }
}
AppearanceAttribute
[Appearance]
属性は、外観マネージャーが導入された iOS 5 に制限されています。
[Appearance]
属性は、UIAppearance
フレームワークに参加する任意のメソッドまたはプロパティに適用できます。 この属性がクラス内のメソッドまたはプロパティに適用されると、バインディング ジェネレーターに対し、このクラスのすべてのインスタンス、または特定の条件に一致するインスタンスのスタイルを設定するために使用される厳密に型指定された外観クラスを作成するように指示します。
例:
public interface UIToolbar {
[Export ("setBackgroundImage:forToolbarPosition:barMetrics:")]
[Appearance]
void SetBackgroundImage (UIImage backgroundImage, UIToolbarPosition position, UIBarMetrics barMetrics);
[Export ("backgroundImageForToolbarPosition:barMetrics:")]
[Appearance]
UIImage GetBackgroundImage (UIToolbarPosition position, UIBarMetrics barMetrics);
}
上記では、UIToolbar で次のコードが生成されます。
public partial class UIToolbar {
public partial class UIToolbarAppearance : UIView.UIViewAppearance {
public virtual void SetBackgroundImage (UIImage backgroundImage, UIToolbarPosition position, UIBarMetrics barMetrics);
public virtual UIImage GetBackgroundImage (UIToolbarPosition position, UIBarMetrics barMetrics)
}
public static new UIToolbarAppearance Appearance { get; }
public static new UIToolbarAppearance AppearanceWhenContainedIn (params Type [] containers);
}
AutoReleaseAttribute (Xamarin.iOS 5.4)
メソッドとプロパティに [AutoReleaseAttribute]
を使用して、メソッド呼び出しを NSAutoReleasePool
でそのメソッドにラップします。
Objective-C には、既定の NSAutoReleasePool
に追加される値を返すメソッドがいくつかあります。 既定では、これらはスレッド NSAutoReleasePool
に送られますが、Xamarin.iOS はマネージド オブジェクトが存在する限りオブジェクトへの参照も保持するため、NSAutoReleasePool
に余分な参照を保持しないようにする場合があります。この参照は、そのままではスレッドが次のスレッドに制御を返すまで、または、メイン ループに戻るまではドレインされません。
この属性は、たとえば既定の NSAutoReleasePool
に追加されたオブジェクトを返す重いプロパティ (UIImage.FromFile
など) に適用されます。 この属性がないと、スレッドがメイン ループに制御を返さない限り、イメージは保持されます。 スレッドが、常に活動しているバックグラウンド ダウンローダーのようなもので、実行を待機していた場合、このイメージがリリースされることはありません。
ForcedTypeAttribute
[ForcedTypeAttribute]
は、返されたアンマネージド オブジェクトがバインド定義で記述されている型と一致しない場合でも、マネージド型の作成を強制するために使用されます。
これは、ヘッダーで記述されている型がネイティブ メソッドの返された型と一致しない場合に便利です。たとえば、NSURLSession
から次の Objective-C 定義を取得します。
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
これは、NSURLSessionDownloadTask
インスタンスを返すと明確に述べていますが、返されるのは、スーパークラスであり、そのために NSURLSessionDownloadTask
に変換できない NSURLSessionTask
です。 タイプ セーフなコンテキストであるために、InvalidCastException
が発生します。
ヘッダーの説明に準拠し、InvalidCastException
を回避するために、[ForcedTypeAttribute]
が使用されます。
[BaseType (typeof (NSObject), Name="NSURLSession")]
interface NSUrlSession {
[Export ("downloadTaskWithRequest:")]
[return: ForcedType]
NSUrlSessionDownloadTask CreateDownloadTask (NSUrlRequest request);
}
[ForcedTypeAttribute]
では、既定で [ForcedType (owns: true)]
である false
の Owns
という名前のブール値も受け取ります。 owns パラメーターは、Core Foundation オブジェクトの所有権ポリシーに従うために使用されます。
[ForcedTypeAttribute]
は、パラメーター、プロパティ、戻り値でのみ有効です。
BindAsAttribute
[BindAsAttribute]
を使用すると、NSNumber
、NSValue
、NSString
(列挙型) をより正確な C# 型にバインドできます。 この属性を使用すると、ネイティブ API よりも優れた、より正確な .NET API を作成できます。
メソッド (戻り値)、パラメーター、プロパティを BindAs
を使用して装飾できます。 唯一の制限は、メンバーは [Protocol]
または [Model]
インターフェイス内部にできないことです。
次に例を示します。
[return: BindAs (typeof (bool?))]
[Export ("shouldDrawAt:")]
NSNumber ShouldDraw ([BindAs (typeof (CGRect))] NSValue rect);
次のように出力されます。
[Export ("shouldDrawAt:")]
bool? ShouldDraw (CGRect rect) { ... }
内部的には、bool?
<->NSNumber
変換と CGRect
<->NSValue
変換を行います。
現在サポートされているカプセル化の種類は次のとおりです。
NSValue
NSNumber
NSString
NSValue
次の C# データ型は、NSValue
との間のカプセル化がサポートされています。
- CGAffineTransform
- NSRange
- CGVector
- SCNMatrix4
- CLLocationCoordinate2D
- SCNVector3
- SCNVector4
- CGPoint / PointF
- CGRect / RectangleF
- CGSize / SizeF
- UIEdgeInsets
- UIOffset
- MKCoordinateSpan
- CMTimeRange
- CMTime
- CMTimeMapping
- CATransform3D
NSNumber
次の C# データ型は、NSNumber
との間のカプセル化がサポートされています。
- [bool]
- byte
- 倍精度浮動小数点
- float
- short
- int
- long
- sbyte
- ushort
- uint
- ulong
- nfloat
- nint
- nuint
- 列挙型
NSString
[BindAs]
は、NSString 定数に基づく列挙型と組み合わせて機能することで、よりよい .NET API を構築できます。次に例を示します。
[BindAs (typeof (CAScroll))]
[Export ("supportedScrollMode")]
NSString SupportedScrollMode { get; set; }
次のように出力されます。
[Export ("supportedScrollMode")]
CAScroll SupportedScrollMode { get; set; }
enum
<->NSString
変換は、[BindAs]
への指定された列挙型が NSString 定数に基づく場合にのみ処理します。
配列
[BindAs]
では、サポートされている任意の型の配列もサポートされます。例として、次の API 定義を使用できます。
[return: BindAs (typeof (CAScroll []))]
[Export ("getScrollModesAt:")]
NSString [] GetScrollModes ([BindAs (typeof (CGRect []))] NSValue [] rects);
次のように出力されます。
[Export ("getScrollModesAt:")]
CAScroll? [] GetScrollModes (CGRect [] rects) { ... }
rects
パラメーターは、各 CGRect
の NSValue
を含む NSArray
にカプセル化され、その戻り値として、NSStrings
を含む返された NSArray
の値を使用して作成された CAScroll?
の配列を取得します。
BindAttribute
この [Bind]
属性には、メソッドまたはプロパティ宣言に適用する場合は 1 つ、プロパティ内の個々のゲッターまたはセッターに適用する場合は 2 つの用途があります。
メソッドまたはプロパティに使用する場合、[Bind]
属性の効果は、指定したセレクターを呼び出すメソッドを生成することです。 しかし、生成されたメソッドは [Export]
属性で修飾されていないため、メソッドのオーバーライドに参加できません。 これは通常、Objective-C 拡張メソッドを実装するために [Target]
属性と組み合わせて使用されます。
次に例を示します。
public interface UIView {
[Bind ("drawAtPoint:withFont:")]
SizeF DrawString ([Target] string str, CGPoint point, UIFont font);
}
ゲッターまたはセッターで使用する場合、[Bind]
属性は、プロパティのゲッターおよびセッターそれぞれの Objective-C セレクター名生成時にコード ジェネレーターが推論する既定値を変更するために使用されます。 既定では、fooBar
という名前のプロパティにフラグを設定すると、ジェネレーターはゲッターの fooBar
エクスポートとセッターの setFooBar:
エクスポートを生成します。 いくつかのケースでは、Objective-C はこの規則に従わず、通常、ゲッター名を isFooBar
に変更します。
この属性を使用して、これをジェネレーターに通知します。
次に例を示します。
// Default behavior
[Export ("active")]
bool Active { get; set; }
// Custom naming with the Bind attribute
[Export ("visible")]
bool Visible { [Bind ("isVisible")] get; set; }
AsyncAttribute
Xamarin.iOS 6.3 以降でのみ使用できます。
この属性は、完了ハンドラーを最後の引数として受け取るメソッドに適用できます。
[Async]
属性は、最後の引数がコールバックであるメソッドで使用できます。 これをメソッドに適用すると、バインディング ジェネレーターによって、サフィックス Async
を持つそのメソッドのバージョンが生成されます。 コールバックがパラメーターを受け取らない場合、戻り値は Task
になります。コールバックがパラメーターを受け取る場合、結果は Task<T>
になります。
[Export ("upload:complete:")]
[Async]
void LoadFile (string file, NSAction complete)
この非同期メソッドは次のように生成されます。
Task LoadFileAsync (string file);
コールバックが複数のパラメーターを受け取る場合、すべてのプロパティを保持する生成された型の目的の名前を指定するように、ResultType
または ResultTypeName
を設定する必要があります。
delegate void OnComplete (string [] files, nint byteCount);
[Export ("upload:complete:")]
[Async (ResultTypeName="FileLoading")]
void LoadFiles (string file, OnComplete complete)
次の例では、この非同期メソッドが生成されます。ここで、FileLoading
に files
と byteCount
の両方にアクセスするためのプロパティが含まれます。
Task<FileLoading> LoadFile (string file);
コールバックの最後のパラメーターが NSError
の場合、生成された Async
メソッドはその値が null でないことを確認し、その場合、生成された非同期メソッドによってタスク例外が設定されます。
[Export ("upload:onComplete:")]
[Async]
void Upload (string file, Action<string,NSError> onComplete);
上記では、次の非同期メソッドが生成されます。
Task<string> UploadAsync (string file);
エラーが発生すると、結果のタスクは、結果の NSError
をラップする NSErrorException
に設定された例外を受け取ります。
AsyncAttribute.ResultType
このプロパティを使用して、返される Task
オブジェクトの値を指定します。 このパラメーターは既存の型を受け取ります。そのため、コア API 定義のいずれかで定義する必要があります。
AsyncAttribute.ResultTypeName
このプロパティを使用して、返される Task
オブジェクトの値を指定します。 このパラメーターは目的の型名を受け取ります。ジェネレーターは、コールバックが受け取るパラメーターごとに 1 つずつ、一連のプロパティを生成します。
AsyncAttribute.MethodName
生成される非同期メソッドの名前をカスタマイズするには、このプロパティを使用します。 既定では、メソッドの名前を使用し、"Async" というテキストを追加します。これを使用して、この既定値を変更できます。
DesignatedInitializerAttribute
この属性がコンストラクターに適用されると、最終的なプラットフォーム アセンブリで同じ [DesignatedInitializer]
が生成されます。 これは、サブクラスで使用するコンストラクターを IDE が示すのに役立ちます。
これは、__attribute__((objc_designated_initializer))
の Objective-C/clang の使用にマップする必要があります。
DisableZeroCopyAttribute
この属性は文字列パラメーターまたは文字列プロパティに適用され、このパラメーターに対してコピーゼロの文字列マーシャリングを使用しないようにコード ジェネレーターに指示し、代わりに C# 文字列から新しい NSString インスタンスを作成します。
この属性は、--zero-copy
コマンド ライン オプションを使用するか、アセンブリ レベルの属性 ZeroCopyStringsAttribute
を設定するかのいずれかで、ゼロ コピー文字列マーシャリングを使用するようにジェネレーターに指示する場合にのみ、文字列に必要です。
これは、プロパティが copy
プロパティでなく retain
または assign
プロパティになるように Objective-C で宣言されている場合に必要です。 これらは通常、開発者によって誤って "最適化" されたサード パーティ製ライブラリで発生します。 一般に、retain
プロパティまたは assign
NSString
プロパティは正しくありません。これは、NSMutableString
または NSString
のユーザー派生クラスが、ライブラリ コードの知識なく文字列の内容を変更し、アプリケーションをわずかな損害を与える可能性があるためです。 通常、これは早期の最適化が原因で発生します。
次に、Objective-C の 2 つのプロパティを示します。
@property(nonatomic,retain) NSString *name;
@property(nonatomic,assign) NSString *name2;
DisposeAttribute
[DisposeAttribute]
をクラスに適用する場合は、クラスの Dispose()
メソッド実装に追加されるコード スニペットを指定します。
Dispose
メソッドは bgen
ツールによって自動的に生成されるため、[Dispose]
属性を使用して、生成された Dispose
メソッドの実装にコードを挿入する必要があります。
次に例を示します。
[BaseType (typeof (NSObject))]
[Dispose ("if (OpenConnections > 0) CloseAllConnections ();")]
interface DatabaseConnection {
}
ExportAttribute
[Export]
属性は、Objective-C ランタイムに公開されるメソッドまたはプロパティにフラグを設定するために使用されます。 この属性は、バインド ツールと、実際の Xamarin.iOS ランタイムと Xamarin.Mac ランタイムの間で共有されます。 メソッドの場合、パラメーターは生成されたコードに逐語的に渡されます。プロパティの場合、基本宣言に基づいてゲッターとセッターのエクスポートが生成されます (バインド ツールの動作を変更する方法については、[BindAttribute]
のセクションを参照してください)。
構文:
public enum ArgumentSemantic {
None, Assign, Copy, Retain.
}
[AttributeUsage (AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)]
public class ExportAttribute : Attribute {
public ExportAttribute();
public ExportAttribute (string selector);
public ExportAttribute (string selector, ArgumentSemantic semantic);
public string Selector { get; set; }
public ArgumentSemantic ArgumentSemantic { get; set; }
}
selector は、バインドされる基になる Objective-C メソッドまたはプロパティの名前を表します。
ExportAttribute.ArgumentSemantic
FieldAttribute
この属性は、必要に応じて読み込まれ、C# コードに公開されるフィールドとして C グローバル変数を公開するために使用されます。 通常、これは、C または Objective-C で定義される値を取得するために必要であり、一部の API で使用されるトークンか、値が不透明でありユーザー コードでそのまま使用する必要がある定数の値のいずれかである可能性があります。
構文:
public class FieldAttribute : Attribute {
public FieldAttribute (string symbolName);
public FieldAttribute (string symbolName, string libraryName);
public string SymbolName { get; set; }
public string LibraryName { get; set; }
}
symbolName
は、リンク先の C シンボルです。 既定では、これは、型が定義されている名前空間から名前が推論されるライブラリから読み込まれます。 これがそ、シンボルが検索されるライブラリでない場合は、libraryName
パラメーターを渡す必要があります。 スタティック ライブラリをリンクする場合は、__Internal
を libraryName
パラメーターとして使用します。
生成されるプロパティは常に静的です。
Field 属性でフラグが設定されたプロパティには、次の型を指定できます。
NSString
NSArray
nint
/int
/long
nuint
/uint
/ulong
nfloat
/float
double
CGSize
System.IntPtr
- 列挙型
セッターは、NSString 定数に基づく列挙型ではサポートされませんが、必要に応じて手動でバインドできます。
例:
[Static]
interface CameraEffects {
[Field ("kCameraEffectsZoomFactorKey", "CameraLibrary")]
NSString ZoomFactorKey { get; }
}
InternalAttribute
[Internal]
属性はメソッドまたはプロパティに適用でき、生成されたコードに internal
C# キーワードを使用してフラグを設定し、生成されたアセンブリ内のコードにのみアクセスできるようにする効果があります。 これは通常、レベルが低すぎる API を非表示にし、将来改善する次善のパブリック API を提供し、ジェネレーターでサポートされておらず手動でのコーディングが必要な API に対して使用されます。
バインディングを設計するときは、通常、この属性を使用してメソッドまたはプロパティを非表示にし、メソッドまたはプロパティに別の名前を指定します。次に、C# の補完的なサポート ファイルに、基になる機能を公開する厳密に型指定されたラッパーを追加します。
次に例を示します。
[Internal]
[Export ("setValue:forKey:")]
void _SetValueForKey (NSObject value, NSObject key);
[Internal]
[Export ("getValueForKey:")]
NSObject _GetValueForKey (NSObject key);
次に、サポート ファイルで、次のようなコードを作成できます。
public NSObject this [NSObject idx] {
get {
return _GetValueForKey (idx);
}
set {
_SetValueForKey (value, idx);
}
}
IsThreadStaticAttribute
この属性は、.NET [ThreadStatic]
属性で注釈を付けるプロパティのバッキング フィールドにフラグを設定します。 これは、フィールドがスレッドの静的変数である場合に便利です。
MarshalNativeExceptions (Xamarin.iOS 6.0.6)
この属性により、メソッドはネイティブ (Objective-C) 例外をサポートします。
この呼び出しは、objc_msgSend
を直接呼び出す代わりに、ObjectiveC 例外をキャッチし、マネージド例外にマーシャリングするカスタム トランポリンを経由します。
現在サポートされている objc_msgSend
署名はごくわずかですが (バインドを使用するアプリのネイティブ リンクが失敗し、xamarin__objc_msgSend シンボルが見つからない場合は、署名がサポートされていないことがわかります)、要求に応じてさらに追加できます。
NewAttribute
この属性は、ジェネレーターが宣言の前に new
キーワードを生成するために、メソッドとプロパティに適用されます。
これは、基底クラスに既に存在するサブクラスで同じメソッドまたはプロパティ名が導入された場合に、コンパイラの警告を回避するために使用されます。
NotificationAttribute
この属性をフィールドに適用して、ジェネレーターで厳密に型指定されたヘルパー通知クラスを生成できます。
この属性は、ペイロードを含まない通知の引数なしで使用できます。または、API 定義内の別のインターフェイスを参照する System.Type
を指定することもできます。通常、これらには名前の末尾に "EventArgs" が付いています。 ジェネレーターは、インターフェイスを EventArgs
サブクラス化するクラスに変換し、そこに一覧表示されているすべてのプロパティを含めます。 [Export]
属性は、EventArgs
クラスで Objective-C ディクショナリを検索して値をフェッチするために使用するキーの名前を一覧表示するために使用する必要があります。
次に例を示します。
interface MyClass {
[Notification]
[Field ("MyClassDidStartNotification")]
NSString DidStartNotification { get; }
}
上記のコードでは、次のメソッドを使用して入れ子になったクラス MyClass.Notifications
が生成されます。
public class MyClass {
[..]
public Notifications {
public static NSObject ObserveDidStart (EventHandler<NSNotificationEventArgs> handler)
public static NSObject ObserveDidStart (NSObject objectToObserve, EventHandler<NSNotificationEventArgs> handler)
}
}
その後、コードのユーザーは、次のようなコードを使用して、NSDefaultCenter に投稿された通知を簡単にサブスクライブできます。
var token = MyClass.Notifications.ObserverDidStart ((notification) => {
Console.WriteLine ("Observed the 'DidStart' event!");
});
または、観察する特定のオブジェクトを設定します。 null
を objectToObserve
に渡すと、このメソッドは他のピアと同じように動作します。
var token = MyClass.Notifications.ObserverDidStart (objectToObserve, (notification) => {
Console.WriteLine ("Observed the 'DidStart' event on objectToObserve!");
});
次のように、ObserveDidStart
の戻り値を使用して、通知の受信を簡単に停止できます。
token.Dispose ();
または、NSNotification.DefaultCenter.RemoveObserver を呼び出して、トークンを渡すことができます。 通知にパラメーターが含まれている場合は、次のようにヘルパー EventArgs
インターフェイスを指定する必要があります。
interface MyClass {
[Notification (typeof (MyScreenChangedEventArgs)]
[Field ("MyClassScreenChangedNotification")]
NSString ScreenChangedNotification { get; }
}
// The helper EventArgs declaration
interface MyScreenChangedEventArgs {
[Export ("ScreenXKey")]
nint ScreenX { get; set; }
[Export ("ScreenYKey")]
nint ScreenY { get; set; }
[Export ("DidGoOffKey")]
[ProbePresence]
bool DidGoOff { get; }
}
上記では、ScreenX
プロパティと ScreenY
プロパティを持つ MyScreenChangedEventArgs
クラスが生成され、NSNotification.UserInfo ディクショナリから、それぞれ ScreenXKey
キーと ScreenYKey
キーを使用してデータがフェッチされ、適切な変換が適用されます。 [ProbePresence]
属性は、値を抽出するのでなく、UserInfo
でキーが設定されているかどうかをジェネレーターがプローブするために使用されます。 これは、キーの存在が値である場合に使用されます (通常はブール値の場合)。
これにより、次のようなコードを記述できます。
var token = MyClass.NotificationsObserveScreenChanged ((notification) => {
Console.WriteLine ("The new screen dimensions are {0},{1}", notification.ScreenX, notification.ScreenY);
});
場合によっては、ディクショナリで渡される値に関連付けられている定数はありません。 Apple ではパブリック シンボル定数を使用する場合もあれば、文字列定数を使用する場合もあります。 既定では、指定した EventArgs
クラスの [Export]
属性は、指定した名前を実行時に参照するパブリック シンボルとして使用します。 そうでない場合は、代わりに文字列定数として検索され、ArgumentSemantic.Assign
値を Export 属性に渡します。
Xamarin.iOS 8.4 の新機能
場合によっては、通知は引数なしで有効期間を開始するため、引数を指定せずに [Notification]
を使用できます。 ただし、通知のパラメーターが導入される場合があります。 このシナリオをサポートするために、属性を複数回適用できます。
バインドを開発していて、既存のユーザー コードを壊さないようにする場合は、既存の通知を次の場所から有効にします。
interface MyClass {
[Notification]
[Field ("MyClassScreenChangedNotification")]
NSString ScreenChangedNotification { get; }
}
通知属性を 2 回一覧表示するバージョンには、次のようになります。
interface MyClass {
[Notification]
[Notification (typeof (MyScreenChangedEventArgs)]
[Field ("MyClassScreenChangedNotification")]
NSString ScreenChangedNotification { get; }
}
NullAllowedAttribute
これがプロパティに適用されると、プロパティに値 null
を割り当てられるようにフラグが設定されます。 これは参照型に対してのみ有効です。
これがメソッド シグネチャのパラメーターに適用される場合、指定されたパラメーターを null にでき、null
値を渡すためのチェックを実行する必要がないことを示せます。
参照型にこの属性がない場合、バインディング ツールは割り当てられている値のチェックを生成してから Objective-C に渡し、割り当てられた値が null
の場合に ArgumentNullException
をスローするチェックを生成します。
次に例を示します。
// In properties
[NullAllowed]
UIImage IconFile { get; set; }
// In methods
void SetImage ([NullAllowed] UIImage image, State forState);
OverrideAttribute
この属性を使用して、この特定のメソッドのバインドに override
キーワードを使用してフラグを設定する必要があることをバインディング ジェネレーターに指示します。
PreSnippetAttribute
この属性を使用すると、入力パラメーターが検証された後、コードが Objective-C に呼び出される前に、挿入されるコードを挿入できます。
例:
[Export ("demo")]
[PreSnippet ("var old = ViewController;")]
void Demo ();
PrologueSnippetAttribute
この属性を使用して、生成されたメソッドでパラメーターのいずれかが検証される前に挿入されるコードを挿入できます。
例:
[Export ("demo")]
[Prologue ("Trace.Entry ();")]
void Demo ();
PostGetAttribute
このクラスから指定したプロパティを呼び出して、そこから値をフェッチするようにバインディング ジェネレーターに指示します。
このプロパティは、通常、オブジェクト グラフを参照し続けるオブジェクトを参照するキャッシュを更新するために使用されます。 通常は、Add/Remove などの演算子を含むコードに表示されます。 このメソッドは、要素を追加または削除した後に内部キャッシュを更新して、実際に使用されているオブジェクトへのマネージド参照を確実に保持するために使用されます。 これは、バインディング ツールが特定のバインディング内のすべての参照オブジェクトのバッキング フィールドを生成するためです。
例:
[BaseType (typeof (NSObject))]
public interface NSOperation {
[Export ("addDependency:")][PostGet ("Dependencies")]
void AddDependency (NSOperation op);
[Export ("removeDependency:")][PostGet ("Dependencies")]
void RemoveDependency (NSOperation op);
[Export ("dependencies")]
NSOperation [] Dependencies { get; }
}
この場合、Dependencies
プロパティは、NSOperation
オブジェクトの依存関係を追加または削除した後に呼び出され、実際に読み込まれたオブジェクトを表すグラフが作成され、メモリ リークとメモリ破損の両方が防止されます。
PostSnippetAttribute
この属性を使用すると、基になる Objective-C メソッドを呼び出した後に、挿入される C# ソース コードを挿入できます
例:
[Export ("demo")]
[PostSnippet ("if (old != null) old.DemoComplete ();")]
void Demo ();
ProxyAttribute
この属性は、プロキシ オブジェクトとしてフラグを設定する値を返すために適用されます。 一部の Objective-C API は、ユーザー バインドとは区別できないプロキシ オブジェクトを返します。 この属性の効果は、オブジェクトに DirectBinding
オブジェクトとしてフラグを設定することです。 Xamarin.Mac のシナリオについては、このバグに関する説明を参照してください。
ReleaseAttribute (Xamarin.iOS 6.0)
これを戻り値の型に適用して、ジェネレーターがオブジェクトに対して Release
を呼び出してから返す必要があることを示せます。 これは、最も一般的なシナリオである自動リリース オブジェクトとは対照的に、メソッドが保持オブジェクトを提供する場合にのみ必要です
例:
[Export ("getAndRetainObject")]
[return: Release ()]
NSObject GetAndRetainObject ();
さらに、この属性は生成されたコードに伝達されるため、Xamarin.iOS ランタイムは、そのような関数から Objective-C に戻る際に、オブジェクトを保持する必要があることを認識します。
SealedAttribute
生成されたメソッドにシールとしてフラグを設定するようにジェネレーターに指示します。 この属性が指定されていない場合、既定では仮想メソッド (仮想メソッド、抽象メソッド、または他の属性の使用方法に応じたオーバーライド) が生成されます。
StaticAttribute
[Static]
属性がメソッドまたはプロパティに適用されると、静的メソッドまたはプロパティが生成されます。 この属性が指定されていない場合、ジェネレーターはインスタンス メソッドまたはプロパティを生成します。
TransientAttribute
この属性を使用して、値が一時的であるプロパティ、つまり iOS によって一時的に作成されるが有効期間が長くないオブジェクトにフラグを設定します。 この属性をプロパティに適用すると、ジェネレーターはこのプロパティのバッキング フィールドを作成しません。つまり、マネージド クラスはオブジェクトへの参照を保持しません。
WrapAttribute
Xamarin.iOS/Xamarin.Mac バインドの設計では、[Wrap]
属性を使用して、厳密に型指定されたオブジェクトで弱く型指定されたオブジェクトをラップします。 これは主に、id
型または NSObject
型として宣言される Objective-C デリゲート オブジェクトで行われます。 Xamarin.iOS および Xamarin.Mac で使用される規則は、これらのデリゲートまたはデータ ソースを NSObject
型として公開し、"弱い" という規則と公開される名前を使用して名前を付けます。 Objective-C からの id delegate
プロパティは、API コントラクト ファイルの NSObject WeakDelegate { get; set; }
プロパティとして公開されます。
ただし、通常、このデリゲートに割り当てられる値は厳密な型であるため、厳密な型を表示し、[Wrap]
属性を適用します。つまり、ユーザーは、細かい制御が必要な場合や、低レベルのトリックに頼る必要がある場合、またはほとんどの作業で厳密に型指定されたプロパティを使用できる場合、弱い型を使用することを選択できます。
例:
[BaseType (typeof (NSObject))]
interface Demo {
[Export ("delegate"), NullAllowed]
NSObject WeakDelegate { get; set; }
[Wrap ("WeakDelegate")]
DemoDelegate Delegate { get; set; }
}
[BaseType (typeof (NSObject))]
[Model][Protocol]
interface DemoDelegate {
[Export ("doDemo")]
void DoDemo ();
}
これは、ユーザーが弱く型指定されたバージョンのデリゲートを使用する方法です。
// The weak case, user has to roll his own
class SomeObject : NSObject {
[Export ("doDemo")]
void CallbackForDoDemo () {}
}
var demo = new Demo ();
demo.WeakDelegate = new SomeObject ();
これは、ユーザーが厳密に型指定されたバージョンを使用する場合の方法であり、ユーザーが C# の型システムを利用し、override キーワードを使用して意図する型を宣言し、[Export]
を使用してメソッドを手動で装飾する必要がありません。これは、ユーザーのために既にバインドしてあるためです。
// This is the strong case,
class MyDelegate : DemoDelegate {
override void Demo DoDemo () {}
}
var strongDemo = new Demo ();
demo.Delegate = new MyDelegate ();
[Wrap]
属性のもう 1 つの用途は、厳密に型指定されたバージョンのメソッドをサポートすることです。 次に例を示します。
[BaseType (typeof (NSObject))]
interface XyzPanel {
[Export ("playback:withOptions:")]
void Playback (string fileName, [NullAllowed] NSDictionary options);
[Wrap ("Playback (fileName, options?.Dictionary")]
void Playback (string fileName, XyzOptions options);
}
[Category]
属性で修飾された型内のメソッドに [Wrap]
属性を適用する場合は、拡張メソッドが生成されるため、最初の引数として This
を含める必要があります。 次に例を示します。
[Wrap ("Write (This, image, options?.Dictionary, out error)")]
bool Write (CIImage image, CIImageRepresentationOptions options, out NSError error);
[Wrap]
によって生成されたメンバーは、既定では virtual
ではありません。virtual
メンバーが必要な場合は、省略可能な isVirtual
パラメーターを true
に設定できます。
[BaseType (typeof (NSObject))]
interface FooExplorer {
[Export ("fooWithContentsOfURL:")]
void FromUrl (NSUrl url);
[Wrap ("FromUrl (NSUrl.FromString (url))", isVirtual: true)]
void FromUrl (string url);
}
[Wrap]
は、プロパティ ゲッターとプロパティ セッターで直接使用することもできます。
これにより、それらを完全に制御し、必要に応じてコードを調整できます。
たとえば、スマート列挙型を使用する次の API 定義を考えてみましょう。
// Smart enum.
enum PersonRelationship {
[Field (null)]
None,
[Field ("FMFather", "__Internal")]
Father,
[Field ("FMMother", "__Internal")]
Mother
}
インターフェイス定義:
// Property definition.
[Export ("presenceType")]
NSString _PresenceType { get; set; }
PersonRelationship PresenceType {
[Wrap ("PersonRelationshipExtensions.GetValue (_PresenceType)")]
get;
[Wrap ("_PresenceType = value.GetConstant ()")]
set;
}
パラメーター属性
このセクションでは、メソッド定義のパラメーターに適用できる属性と、プロパティ全体に適用される [NullAttribute]
について説明します。
BlockCallback
この属性は、C# デリゲート宣言のパラメーター型に適用され、問題のパラメーターが Objective-C ブロック呼び出し規則に準拠しており、この方法でマーシャリングする必要があることをバインダーに通知します。
これは通常、Objective-C で次のように定義されているコールバックに使用されます。
typedef returnType (^SomeTypeDefinition) (int parameter1, NSString *parameter2);
CCallback も参照してください。
CCallback
この属性は、C# デリゲート宣言のパラメーター型に適用され、問題のパラメーターが C ABI 関数ポインター呼び出し規則に準拠しており、この方法でマーシャリングする必要があることをバインダーに通知します。
これは通常、Objective-C で次のように定義されているコールバックに使用されます。
typedef returnType (*SomeTypeDefinition) (int parameter1, NSString *parameter2);
BlockCallback も参照してください。
パラメーター
メソッド定義の最後の配列パラメーターで [Params]
属性を使用して、ジェネレーターに定義に "params" を挿入させることができます。 これにより、バインディングで省略可能なパラメーターを簡単に使用できます。
たとえば、次の定義です。
[Export ("loadFiles:")]
void LoadFiles ([Params]NSUrl [] files);
次のコードを記述できるようにします。
foo.LoadFiles (new NSUrl (url));
foo.LoadFiles (new NSUrl (url1), new NSUrl (url2), new NSUrl (url3));
これには、ユーザーは要素を渡すためだけに配列を作成する必要がないという追加の利点があります。
PlainString
[PlainString]
属性を文字列パラメーターの前に使用して、パラメーターを NSString
として渡す代わりに、文字列を C 文字列として渡すようにバインド ジェネレーターに指示できます。
ほとんどの Objective-C API は NSString
パラメーターを使用しますが、一部の API では、NSString
のバリエーションでなく、文字列を渡すための char *
API を公開します。
その場合、[PlainString]
を使用します。
たとえば、次の Objective-C 宣言があります。
- (void) setText: (NSString *) theText;
- (void) logMessage: (char *) message;
次のようにバインドする必要があります。
[Export ("setText:")]
void SetText (string theText);
[Export ("logMessage:")]
void LogMessage ([PlainString] string theText);
RetainAttribute
指定したパラメーターへの参照を保持するようにジェネレーターに指示します。 ジェネレーターは、このフィールドのバッキング ストアを提供するか、値を格納する名前 (WrapName
) を指定できます。 これは、Objective-C のパラメーターとして渡されるマネージド オブジェクトへの参照を保持し、Objective-C がオブジェクトのこのコピーのみを保持することがわかっている場合に便利です。 たとえば、SetDisplay (SomeObject)
のような API では、SetDisplay で一度に表示できるオブジェクトが 1 つだけである可能性があるため、この属性が使用されます。 複数のオブジェクト (たとえば、スタックに似た API) を追跡する必要がある場合は、[RetainList]
属性を使用します。
構文:
public class RetainAttribute {
public RetainAttribute ();
public RetainAttribute (string wrapName);
public string WrapName { get; }
}
TransientAttribute
この属性はパラメーターに適用され、Objective-C から C# に移行する場合にのみ使用されます。 これらの遷移中に、さまざまな Objective-CNSObject
パラメーターがオブジェクトのマネージド表現にラップされます。
ランタイムはネイティブ オブジェクトへの参照を受け取り、オブジェクトへの最後のマネージド参照がなくなるまで参照を保持し、GC を実行できます。
場合によっては、C# ランタイムがネイティブ オブジェクトへの参照を保持しないことが重要です。 これは、基になるネイティブ コードがパラメーターのライフサイクルに特別な動作をアタッチした場合に発生することがあります。 たとえば、パラメーターのデストラクターは、クリーンアップ アクションを実行し、貴重なリソースを破棄します。
この属性は、上書きされたメソッドから Objective-C に戻るときに、可能であればオブジェクトを破棄することをランタイムに通知します。
ルールは単純です。ランタイムがネイティブ オブジェクトから新しいマネージド表現を作成する必要がある場合、関数の最後にネイティブ オブジェクトの保持カウントが削除され、マネージド オブジェクトの Handle プロパティがクリアされます。 つまり、マネージド オブジェクトへの参照を保持した場合、その参照は役に立たなくなります (メソッドを呼び出すと例外がスローされます)。
渡されたオブジェクトが作成されなかった場合、またはオブジェクトの未処理のマネージド表現が既に存在する場合、強制破棄は行われません。
プロパティ属性
NotImplementedAttribute
この属性は、getter を持つプロパティが基底クラスで導入され、変更可能なサブクラスがセッターを導入する Objective-C 表現形式をサポートするために使用されます。
C# ではこのモデルがサポートされていないため、基底クラスにはセッターとゲッターの両方が必要であり、サブクラスは OverrideAttribute を使用できます。
この属性はプロパティ セッターでのみ使用され、Objective-C で変更可能な表現形式をサポートするために使用されます。
例:
[BaseType (typeof (NSObject))]
interface MyString {
[Export ("initWithValue:")]
IntPtr Constructor (string value);
[Export ("value")]
string Value {
get;
[NotImplemented ("Not available on MyString, use MyMutableString to set")]
set;
}
}
[BaseType (typeof (MyString))]
interface MyMutableString {
[Export ("value")]
[Override]
string Value { get; set; }
}
列挙属性
NSString
定数の列挙値へのマッピングは、より優れた .NET API を作成するための簡単な方法です。 それでは次のことが行われます。
- これを使用すると、API の正しい値のみを表示することで、コード補完がより便利になります。
- タイプ セーフを追加します。正しくないコンテキストで別の
NSString
定数を使用することはできません。 - これを使用すると、一部の定数を非表示にして、機能を失うことなくコード補完の API リストを短くできます。
例:
enum NSRunLoopMode {
[DefaultEnumValue]
[Field ("NSDefaultRunLoopMode")]
Default,
[Field ("NSRunLoopCommonModes")]
Common,
[Field (null)]
Other = 1000
}
上記のバインド定義から、ジェネレーターは enum
自体を作成し、列挙型の値と NSString
定数の間に双方向変換メソッドを含む *Extensions
静的型も作成します。 これは、定数が API に含まれていない場合でも、開発者が使用できる状態を維持することを意味します。
例 :
// using the NSString constant in a different API / framework / 3rd party code
CallApiRequiringAnNSString (NSRunLoopMode.Default.GetConstant ());
// converting the constants from a different API / framework / 3rd party code
var constant = CallApiReturningAnNSString ();
// back into an enum value
CallApiWithEnum (NSRunLoopModeExtensions.GetValue (constant));
DefaultEnumValueAttribute
この属性を使用して、1 つの列挙値を装飾できます。 列挙型の値が不明な場合、これが返される定数になります。
上記の例の場合:
var x = (NSRunLoopMode) 99;
Call (x.GetConstant ()); // NSDefaultRunLoopMode will be used
列挙型の値が修飾されていない場合は、NotSupportedException
がスローされます。
ErrorDomainAttribute
エラー コードは列挙値としてバインドされます。 エラー領域はよくあるもので、適用する値を見つけることは必ずしも容易でなく、存在するかどうかもわかりません。
この属性を使用して、エラー領域を列挙型自体に関連付けることができます。
例:
[Native]
[ErrorDomain ("AVKitErrorDomain")]
public enum AVKitError : nint {
None = 0,
Unknown = -1000,
PictureInPictureStartFailed = -1001
}
その後、拡張メソッド GetDomain
を呼び出して、エラーのドメイン定数を取得できます。
FieldAttribute
これは、型内の定数に使用されるのと同じ [Field]
属性です。 また、列挙型内で使用して、特定の定数を持つ値をマップすることもできます。
null
値を使用して、null
NSString
定数を指定した場合に返す列挙値を指定できます。
上記の例の場合:
var constant = NSRunLoopMode.NewInWatchOS3; // will be null in watchOS 2.x
Call (NSRunLoopModeExtensions.GetValue (constant)); // will return 1000
null
値が存在しない場合は、ArgumentNullException
がスローされます。
グローバル属性
グローバル属性は、[LinkWithAttribute]
のような [assembly:]
属性修飾子を使用して適用するか、可用性属性などの任意の場所で使用できます。
LinkWithAttribute
これはアセンブリ レベルの属性であり、開発者は、ライブラリのコンシューマーがライブラリに渡される gcc_flags と追加の mtouch 引数を手動で構成することを強制することなく、バインドされたライブラリを再利用するために必要なリンク フラグを指定できます。
構文:
// In properties
[Flags]
public enum LinkTarget {
Simulator = 1,
ArmV6 = 2,
ArmV7 = 4,
Thumb = 8,
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple=true)]
public class LinkWithAttribute : Attribute {
public LinkWithAttribute ();
public LinkWithAttribute (string libraryName);
public LinkWithAttribute (string libraryName, LinkTarget target);
public LinkWithAttribute (string libraryName, LinkTarget target, string linkerFlags);
public bool ForceLoad { get; set; }
public string Frameworks { get; set; }
public bool IsCxx { get; set; }
public string LibraryName { get; }
public string LinkerFlags { get; set; }
public LinkTarget LinkTarget { get; set; }
public bool NeedsGccExceptionHandling { get; set; }
public bool SmartLink { get; set; }
public string WeakFrameworks { get; set; }
}
この属性はアセンブリ レベルで適用されます。たとえば、これが CorePlot バインドが使用するものです。
[assembly: LinkWith ("libCorePlot-CocoaTouch.a", LinkTarget.ArmV7 | LinkTarget.ArmV7s | LinkTarget.Simulator, Frameworks = "CoreGraphics QuartzCore", ForceLoad = true)]
[LinkWith]
属性を使用すると、指定した libraryName
が結果のアセンブリに埋め込まれるので、ユーザーは、Xamarin.iOS からライブラリを適切に使用するために必要なコマンド ライン フラグと、アンマネージド依存関係の両方を含む単一の DLL を出荷できます。
libraryName
を指定しないこともできます。この場合、LinkWith
属性を使用して追加のリンカー フラグのみを指定できます。
[assembly: LinkWith (LinkerFlags = "-lsqlite3")]
LinkWithAttribute コンストラクター
これらのコンストラクターを使用すると、リンクするライブラリを指定し、結果のアセンブリに埋め込むことができます。また、ライブラリでサポートされるサポート対象、およびライブラリとリンクするために必要な任意のライブラリ フラグを指定できます。
LinkTarget
引数は Xamarin.iOS によって推論され、設定する必要はありません。
例 :
// Specify additional linker:
[assembly: LinkWith (LinkerFlags = "-sqlite3")]
// Specify library name for the constructor:
[assembly: LinkWith ("libDemo.a");
// Specify library name, and link target for the constructor:
[assembly: LinkWith ("libDemo.a", LinkTarget.Thumb | LinkTarget.Simulator);
// Specify only the library name, link target and linker flags for the constructor:
[assembly: LinkWith ("libDemo.a", LinkTarget.Thumb | LinkTarget.Simulator, SmartLink = true, ForceLoad = true, IsCxx = true);
LinkWithAttribute.ForceLoad
ForceLoad
プロパティは、ネイティブ ライブラリのリンクに -force_load
リンク フラグを使用するかどうかを決定するために使用されます。 現時点では、これは常に true である必要があります。
LinkWithAttribute.Frameworks
バインドされているライブラリが、任意のフレームワーク (Foundation
および UIKit
以外) でハード要件を満たしている場合は、Frameworks
プロパティを、必要なプラットフォーム フレームワークのスペース区切りリストを含む文字列に設定する必要があります。 たとえば、CoreGraphics
と CoreText
を必要とするライブラリをバインドする場合は、Frameworks
プロパティを "CoreGraphics CoreText"
に設定します。
LinkWithAttribute.IsCxx
既定の C コンパイラ (C コンパイラ) ではなく C++ コンパイラを使用して結果の実行可能ファイルをコンパイルする必要がある場合は、このプロパティを true に設定します。 バインドするライブラリが C++ で記述されている場合は、これを使用します。
LinkWithAttribute.LibraryName
バンドルするアンマネージド ライブラリの名前。 これは拡張子が ".a" のファイルであり、複数のプラットフォーム (シミュレーターの場合は ARM や x86 など) のオブジェクト コードを含めることができます。
以前のバージョンの Xamarin.iOS では、ライブラリでサポートされているプラットフォームを判断するために LinkTarget
プロパティがチェックされましたが、現在はこれが自動検出され、LinkTarget
プロパティは無視されるようになります。
LinkWithAttribute.LinkerFlags
LinkerFlags
文字列は、ネイティブ ライブラリをアプリケーションにリンクするときに必要な追加のリンカー フラグをバインド作成者が指定する方法を提供します。
たとえば、ネイティブ ライブラリに libxml2 と zlib が必要な場合は、LinkerFlags
文字列を "-lxml2 -lz"
に設定します。
LinkWithAttribute.LinkTarget
以前のバージョンの Xamarin.iOS では、ライブラリでサポートされているプラットフォームを判断するために LinkTarget
プロパティがチェックされましたが、現在はこれが自動検出され、LinkTarget
プロパティは無視されるようになります。
LinkWithAttribute.NeedsGccExceptionHandling
リンクするライブラリに GCC 例外処理ライブラリ (gcc_eh) が必要な場合は、このプロパティを true に設定します。
LinkWithAttribute.SmartLink
xamarin.iOS が、ForceLoad
が必要かどうかを判断できるようにするには、SmartLink
プロパティを true に設定する必要があります。
LinkWithAttribute.WeakFrameworks
WeakFrameworks
プロパティは、Frameworks
プロパティと同じように動作します。ただし、リンク時に、-weak_framework
指定子が一覧表示されているフレームワークごとに gcc に渡される点が異なります。
WeakFrameworks
を使用すると、ライブラリとアプリケーションはプラットフォーム フレームワークに弱くリンクできます。そのため、それらのフレームワークが使用可能で、それらに強固な依存関係を使用しない場合は、ライブラリやアプリケーションで使用することも選択できます。強固な依存関係は、ライブラリが新しいバージョンの iOS に追加機能を追加するためのものである場合は有効です。 弱いリンクの詳細については、弱いリンクに関する Apple のドキュメントを参照してください。
弱いリンクの候補として適しているのは、アカウント、Frameworks
、CoreBluetooth
、CoreImage
、GLKit
、NewsstandKit
、Twitter
です。その理由は、これらが iOS 5 でのみ使用できるためです。
AdviceAttribute
この属性を使用して、開発者にとってより便利な可能性がある他の API に関するヒントを提供します。 たとえば、厳密に型指定されたバージョンの API を提供する場合は、弱く型指定された属性でこの属性を使用して、開発者をより適切な API に誘導できます。
この属性の情報はドキュメントに示されており、ツールを開発して、改善方法に関するユーザーの提案を提供できます
RequiresSuperAttribute
これは、[Advice]
属性の特殊なサブクラスであり、メソッドをオーバーライドするには、基本 (オーバーライドされる) メソッドの呼び出しが必要であることを開発者に示すために使用できます。
これは、clang
__attribute__((objc_requires_super))
に対応します
ZeroCopyStringsAttribute
Xamarin.iOS 5.4 以降でのみ使用できます。
この属性は、この特定のライブラリ ([assembly:]
で適用されている場合) または型のバインドで、高速のゼロ コピー文字列マーシャリングを使用する必要があることをジェネレーターに指示します。 この属性は、--zero-copy
コマンド ライン オプションをジェネレーターに渡すことと同じです。
文字列にゼロ コピーを使用する場合、ジェネレーターは、新しい NSString
オブジェクトの作成を発生させることなく、C# 文字列から Objective-C 文字列へのデータのコピーを回避して、Objective-C が使用する文字列と同じ C# 文字列を効果的に使用します。 ゼロ コピー文字列を使用する唯一の欠点は、retain
または copy
としてフラグが付けられるすべてのラップ対象の文字列プロパティに、[DisableZeroCopy]
属性が設定されると確認する必要があることです。 これは、ゼロ コピー文字列のハンドルがスタックに割り当てられ、関数が返されるときに無効であるために必要です。
例:
[ZeroCopyStrings]
[BaseType (typeof (NSObject))]
interface MyBinding {
[Export ("name")]
string Name { get; set; }
[Export ("domain"), NullAllowed]
string Domain { get; set; }
[DisablZeroCopy]
[Export ("someRetainedNSString")]
string RetainedProperty { get; set; }
}
アセンブリ レベルで属性を適用することもできます。この属性は、アセンブリのすべての型に適用されます。
[assembly:ZeroCopyStrings]
厳密に型指定されたディクショナリ
Xamarin.iOS 8.0 では、NSDictionaries
をラップする厳密に型指定されたクラスを簡単に作成するためのサポートが導入されました。
DictionaryContainer データ型を手動 API と併用することは常に可能ですが、この実行が格段に簡単になりました。 詳細については、厳密な型の提示に関する記事を参照してください。
StrongDictionary
この属性がインターフェイスに適用されると、ジェネレーターは、DictionaryContainer から派生したインターフェイスと同じ名前のクラスを生成し、このインターフェイスで定義されている各プロパティを、ディクショナリの厳密に型指定されたゲッターとセッターに変換します。
これにより、既存の NSDictionary
からインスタンス化できるクラス、または新規作成されたクラスが自動的に生成されます。
この属性は、ディクショナリ上の要素にアクセスするために使用されるキーを含むクラスの名前である 1 つのパラメーターを受け取ります。 既定では、属性を持つインターフェイス内の各プロパティは、指定された型のメンバーを検索し、サフィックス "Key" を持つ名前を検索します。
次に例を示します。
[StrongDictionary ("MyOptionKeys")]
interface MyOption {
string Name { get; set; }
nint Age { get; set; }
}
[Static]
interface MyOptionKeys {
// In Objective-C this is "NSString *MYOptionNameKey;"
[Field ("MYOptionNameKey")]
NSString NameKey { get; }
// In Objective-C this is "NSString *MYOptionAgeKey;"
[Field ("MYOptionAgeKey")]
NSString AgeKey { get; }
}
上記の場合、MyOption
クラスは、MyOptionKeys.NameKey
をディクショナリのキーとして使用して文字列を取得する Name
の文字列プロパティを生成します。 また、MyOptionKeys.AgeKey
をディクショナリのキーとして使用して、int を含む NSNumber
を取得します。
別のキーを使用する場合は、プロパティで export 属性を使用できます。次に例を示します。
[StrongDictionary ("MyColoringKeys")]
interface MyColoringOptions {
[Export ("TheName")] // Override the default which would be NameKey
string Name { get; set; }
[Export ("TheAge")] // Override the default which would be AgeKey
nint Age { get; set; }
}
[Static]
interface MyColoringKeys {
// In Objective-C this is "NSString *MYColoringNameKey"
[Field ("MYColoringNameKey")]
NSString TheName { get; }
// In Objective-C this is "NSString *MYColoringAgeKey"
[Field ("MYColoringAgeKey")]
NSString TheAge { get; }
}
厳密なディクショナリ型
StrongDictionary
定義では、次のデータ型がサポートされています。
C# インターフェイス型 | NSDictionary ストレージの種類 |
---|---|
bool |
NSNumber に格納される Boolean |
列挙値 | NSNumber に格納される整数 |
int |
NSNumber に格納される 32 ビット整数 |
uint |
NSNumber に格納される 32 ビット符号なし整数 |
nint |
NSNumber に格納される NSInteger |
nuint |
NSNumber に格納される NSUInteger |
long |
NSNumber に格納される 64 ビット整数 |
float |
NSNumber として格納される 32 ビット整数 |
double |
NSNumber として格納される 64 ビット整数 |
NSObject とサブクラス |
NSObject |
NSDictionary |
NSDictionary |
string |
NSString |
NSString |
NSString |
NSObject の C# Array |
NSArray |
列挙型の C# Array |
NSNumber 値を格納する NSArray |