型のバインド リファレンス ガイド
このドキュメントでは、API コントラクト ファイルに注釈を付けてバインディングと生成されたコードを駆動するために使用できる属性の一覧について説明します
Xamarin.iOS および Xamarin.Mac API コントラクトは、主に C# で、コードを C# に表示する方法を定義する Objective-C インターフェイス定義として記述されます。 このプロセスには、インターフェイス宣言と、API コントラクトに必要な基本的な型定義の組み合わせが含まれます。 バインドの種類の概要については、コンパニオン ガイド「 バインド Objective-C ライブラリ」を参照してください。
型定義
構文:
[BaseType (typeof (BTYPE))
interface MyType : [Protocol1, Protocol2] {
IntPtr Constructor (string foo);
}
属性を持つコントラクト定義内のすべてのインターフェイスは [BaseType]
、生成されたオブジェクトの基本型を宣言します。 上記の宣言では、 というMyType
名前のMyType
型にバインドするクラス C# 型がObjective-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 つの機能は、デリゲート クラスを C# イベントとコールバックとしてマップ Objective-C することです。 ユーザーは、プログラミング パターンを採用Objective-Cするか、ランタイムが呼び出すさまざまなメソッドObjective-Cを実装するクラスのインスタンスなどのDelegate
プロパティに割り当てるか、C#スタイルのイベントとプロパティを選択することで、インスタンスごとに選択できます。
モデルの使用方法の 1 つの例を Objective-C 見てみましょう。
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 クラスも呼び出します)。これは、 パラメーターと Delegates
パラメーターを使用して定義に注釈を[BaseType]
付Events
けることで行われます (後述)。
これらのパラメーターで に [BaseType]
注釈を付けるだけでなく、いくつかのコンポーネントをジェネレーターに通知する必要があります。
複数のパラメーターを受け取るイベントの場合 ( Objective-C 規約では、デリゲート クラスの最初のパラメーターは sender オブジェクトのインスタンスです)、生成される 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
派生する クラスが生成UIImagePickerImagePickedEventArgs
され、 パラメーターと パラメーターの両方がUIImage
パックされますNSDictionary
。 ジェネレーターによって次の結果が生成されます。
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" を使用するため、 型NSUrlConnection
を にマップObjective-CNSURLConnection
します。
[BaseType (typeof (NSObject), Name="NSURLConnection")]
interface NSUrlConnection {
}
指定した名前は、バインドで生成された [Register]
属性の値として使用されます。 が指定されていない場合 Name
、生成された出力の属性の値 [Register]
として型の短い名前が使用されます。
BaseType.Events と BaseType.Delegates
これらのプロパティは、生成されたクラスで C#スタイルのイベントの生成を促進するために使用されます。 これらは、特定のクラスをデリゲート クラスに Objective-C リンクするために使用されます。 クラスがデリゲート クラスを使用して通知とイベントを送信する場合は、多くの場合に発生します。 たとえば、 には BarcodeScanner
コンパニオン BardodeScannerDelegate
クラスがあります。 クラスにはBarcodeScanner
通常、 のBarcodeScannerDelegate
インスタンスを割り当てるプロパティが含まれますが、これは機能しますが、C#のようなスタイルのイベント インターフェイスをユーザーに公開する場合があります。そのような場合は、 属性の プロパティと Delegates
プロパティを[BaseType]
使用Events
します。Delegate
これらのプロパティは常に一緒に設定され、同じ数の要素を持ち、同期を維持する必要があります。配列には 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
のメソッドの名前であるため、 プロパティと Delegates
プロパティを組み合わせてEvents
使用する必要があります。
次の例は、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 使用できる一連のメソッドとプロパティを拡張するために使用されるメカニズムです。 実際には、特定のフレームワークが でリンクされている場合 (たとえば NSObject
) に基底クラスの機能を拡張し、 UIKit
そのメソッドを使用できるようにしますが、新しいフレームワークがリンクされている場合にのみ使用されます。 それ以外の場合は、機能別にクラス内の機能を整理するために使用されます。 これらは、C# 拡張メソッドに似ています。
これは、 のカテゴリのようになります Objective-C。
@interface UIView (MyUIViewExtension)
-(void) makeBackgroundRed;
@end
上記の例は、 メソッド makeBackgroundRed
を使用して のUIView
インスタンスを拡張するライブラリにあります。
それらをバインドするには、インターフェイス定義で [Category]
属性を使用できます。 属性を [Category]
使用する場合、属性の [BaseType]
意味は、拡張する基底クラスを指定するために使用されることから、拡張する型に変わります。
次に、拡張機能を UIView
バインドし、C# 拡張メソッドに変換する方法を示します。
[BaseType (typeof (UIView))]
[Category]
interface MyUIViewExtension {
[Export ("makeBackgroundRed")]
void MakeBackgroundRed ();
}
上記では、拡張メソッドを MyUIViewExtension
含むクラスが MakeBackgroundRed
作成されます。 つまり、任意UIView
のサブクラスで を呼び出MakeBackgroundRed
すようになり、 で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);
これを回避するための推奨事項は、インターフェイス定義自体内の定義をBoolMethod
FooObject
インライン化することです。これにより、意図FooObject.BoolMethod (range)
したとおりにこの拡張機能を呼び出すことができます。
[BaseType (typeof (NSObject))]
interface FooObject {
[Static]
[Export ("boolMethod:")]
bool BoolMethod (NSRange range);
}
定義内でメンバーが見つかるたびに警告 (BI1117) を[Static]
[Category]
発行します。 実際に定義内[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 に応答できるラムダに値を明示的に設定しない場合、この場合の既定値の戻り値は false になり、 属性で DefaultValue
指定した値になります。
[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; }
}
モデル クラスの値を返すメソッドで指定された場合、この属性は、ユーザーが独自のメソッドまたはラムダを指定しなかった場合に、指定されたパラメーターの値を返すようにジェネレーターに指示します。
例:
[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
この属性は、ジェネレーターがホスト クラスで生成されたプロパティの名前を変更できるようにするために使用されます。 場合によっては、Delegate クラスに対して FooDelegate クラス メソッドの名前が理にかなっているが、ホスト クラスではプロパティとして奇数に見える場合に便利です。
また、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 規約では、デリゲート クラスの最初のパラメーターが sender オブジェクトのインスタンスである) の場合は、生成される EventArgs クラスに使用する名前を指定する必要があります。 これは、クラスの [EventArgs]
メソッド宣言の 属性を使用して Model
行われます。
次に例を示します。
[BaseType (typeof (UINavigationControllerDelegate))]
[Model][Protocol]
public interface UIImagePickerControllerDelegate {
[Export ("imagePickerController:didFinishPickingImage:editingInfo:"), EventArgs ("UIImagePickerImagePicked")]
void FinishedPickingImage (UIImagePickerController picker, UIImage image, NSDictionary editingInfo);
}
上記の宣言では、EventArgs から派生したクラスが生成 UIImagePickerImagePickedEventArgs
され、 パラメーターと パラメーターの両方が UIImage
パックされます NSDictionary
。 ジェネレーターによって次の結果が生成されます。
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);
上記では、 の メソッドとして を公開していますがLoadFinished
、 内UIWebViewDelegate
でUIWebView
フックするイベントとして を公開LoadingFinished
しています。
var webView = new UIWebView (...);
webView.LoadFinished += delegate { Console.WriteLine ("done!"); }
ModelAttribute
コントラクト API の型定義に 属性を適用 [Model]
すると、ユーザーが クラス内のメソッドを上書きした場合にのみ、 クラス内のメソッドへの呼び出しを表示する特別なコードがランタイムによって生成されます。 この属性は、通常、デリゲート クラスをラップ Objective-C するすべての API に適用されます。
NoDefaultValueAttribute
モデルの メソッドが既定の戻り値を提供しないことを指定します。
これは、ランタイム要求にObjective-CObjective-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 を簡単に使用できるようにするために、バインディング ツールでは、すべての省略可能なメソッドを公開する extensions メソッド クラスも生成されます。 つまり、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
に が存在しないため、上記が必要です。そのため、空のインターフェイスを指定する必要があります。
プロトコルで生成されたインターフェイスの採用
次のように、プロトコル用に生成されたインターフェイスの 1 つを実装するたびに、
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)
ただし、プロトコル インターフェイスを使用する場合は、[エクスポート] を追加する必要があります。 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
のプロパティで発生します)。 このプロパティを使用してゲッターを装飾し、配置値を使用できます。 これは通常、API と統合されている場合、 OpenTK.Vector4
型と OpenTK.Matrix4
型で Objective-C 使用されます。
例:
public interface GLKBaseEffect {
[Export ("constantColor")]
Vector4 ConstantColor { [Align (16)] get; set; }
}
AppearanceAttribute
属性は [Appearance]
、外観マネージャーが導入された iOS 5 に制限されています。
属性は [Appearance]
、フレームワークに参加する任意のメソッドまたはプロパティに UIAppearance
適用できます。 この属性がクラス内のメソッドまたはプロパティに適用されると、バインディング ジェネレーターは、このクラスのすべてのインスタンス、または特定の条件に一致するインスタンスのスタイルを設定するために使用される厳密に型指定された外観クラスを作成するように指示します。
例:
public interface UIToolbar {
[Since (5,0)]
[Export ("setBackgroundImage:forToolbarPosition:barMetrics:")]
[Appearance]
void SetBackgroundImage (UIImage backgroundImage, UIToolbarPosition position, UIBarMetrics barMetrics);
[Since (5,0)]
[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]
on メソッドと プロパティを使用して、 内の メソッドへのメソッド呼び出しをNSAutoReleasePool
ラップします。
では、既定NSAutoReleasePool
の Objective-C に追加される値を返すメソッドがいくつかあります。 既定では、これらはスレッドNSAutoReleasePool
に移動しますが、Xamarin.iOS はマネージド オブジェクトが存続する限りオブジェクトへの参照も保持するため、スレッドが次のスレッドに制御を戻すか、メイン ループに戻るまでしかドレインされない追加の参照NSAutoReleasePool
を に保持したくない場合があります。
この属性は、たとえば、既定の に追加されたオブジェクトを返す重いプロパティ (例: UIImage.FromFile
) に適用されます NSAutoReleasePool
。 この属性がないと、スレッドがメイン ループに制御を戻さない限り、イメージは保持されます。 Ufあなたのスレッドは、常に生きていると仕事を待っているバックグラウンドダウンローダーのいくつかの並べ替えでした, 画像はリリースされません.
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]
、 という名前Owns
false
のブール値も既定[ForcedType (owns: true)]
で受け入れられます。 owns パラメーターは、Core Foundation オブジェクトの所有権ポリシーに従うために使用されます。
[ForcedTypeAttribute]
は、パラメーター、プロパティ、および戻り値でのみ有効です。
BindAsAttribute
では[BindAsAttribute]
、 と NSValue
NSString
(列挙型) をより正確な C# 型にバインドNSNumber
できます。 属性を使用すると、ネイティブ API よりも優れた、より正確な .NET API を作成できます。
メソッド (戻り値)、パラメーター、およびプロパティを で BindAs
装飾できます。 唯一の制限は、メンバーが または [Model]
インターフェイス内[Protocol]
にいてはなりません。
次に例を示します。
[return: BindAs (typeof (bool?))]
[Export ("shouldDrawAt:")]
NSNumber ShouldDraw ([BindAs (typeof (CGRect))] NSValue rect);
次のように出力されます。
[Export ("shouldDrawAt:")]
bool? ShouldDraw (CGRect rect) { ... }
内部的には、 変換と bool?
<<CGRect
->NSNumber
>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
- double
- 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
<列挙型[BindAs]
が NSString 定数によってサポートされている場合にのみ、 ->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
返された のCAScroll?
値を使用して作成された の配列をNSArray
取得します。
BindAttribute
[Bind]
属性には、メソッドまたはプロパティ宣言に適用する場合は 1 つ、プロパティ内の個々のゲッターまたはセッターに適用する場合は 2 つの使用があります。
メソッドまたはプロパティに使用する場合、属性の [Bind]
効果は、指定したセレクターを呼び出すメソッドを生成することです。 ただし、生成されたメソッドは 属性で [Export]
修飾されません。つまり、メソッドのオーバーライドに参加できません。 これは通常、拡張メソッドを [Target]
実装 Objective-C するための 属性と組み合わせて使用されます。
次に例を示します。
public interface UIView {
[Bind ("drawAtPoint:withFont:")]
SizeF DrawString ([Target] string str, CGPoint point, UIFont font);
}
getter または setter で使用する場合、 属性は、 [Bind]
プロパティのゲッターとセッター Objective-C セレクター名を生成するときにコード ジェネレーターによって推論される既定値を変更するために使用されます。 既定では、 という名前fooBar
のプロパティにフラグを設定すると、ジェネレーターはゲッターとsetFooBar:
セッターのエクスポートを生成fooBar
します。 場合によっては、 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);
コールバックが複数のパラメーターを受け取る場合は、 または ResultTypeName
をResultType
設定して、すべてのプロパティを保持する生成された型の目的の名前を指定する必要があります。
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
値が null でない場合、生成されたAsync
メソッドはチェックし、その場合は、生成された非同期メソッドによってタスク例外が設定されます。
[Export ("upload:onComplete:")]
[Async]
void Upload (string file, Action<string,NSError> onComplete);
上記では、次の非同期メソッドが生成されます。
Task<string> UploadAsync (string file);
また、エラーが発生すると、結果の Task には、結果NSError
の をラップする にNSErrorException
例外が設定されます。
AsyncAttribute.ResultType
このプロパティを使用して、返されるオブジェクトの値を Task
指定します。 このパラメーターは既存の型を受け取ります。そのため、コア API 定義のいずれかで定義する必要があります。
AsyncAttribute.ResultTypeName
このプロパティを使用して、返されるオブジェクトの値を Task
指定します。 このパラメーターは、目的の型名の名前を受け取ります。ジェネレーターは、コールバックが受け取るパラメーターごとに 1 つずつ、一連のプロパティを生成します。
AsyncAttribute.MethodName
生成された非同期メソッドの名前をカスタマイズするには、このプロパティを使用します。 既定では、 メソッドの名前を使用し、"Async" というテキストを追加します。これを使用して、この既定値を変更できます。
DesignatedInitializerAttribute
この属性がコンストラクターに適用されると、最終的なプラットフォーム アセンブリで同じ [DesignatedInitializer]
が生成されます。 これは、サブクラスで使用するコンストラクターを IDE が示すのに役立ちます。
これは、 の /clang の使用__attribute__((objc_designated_initializer))
にObjective-Cマップする必要があります。
DisableZeroCopyAttribute
この属性は文字列パラメーターまたは文字列プロパティに適用され、このパラメーターに対してゼロ コピー文字列マーシャリングを使用しないようにコード ジェネレーターに指示し、代わりに C# 文字列から新しい NSString インスタンスを作成します。
この属性は、コマンド ライン オプションまたはアセンブリ レベル属性 ZeroCopyStringsAttribute
を設定してゼロ コピー文字列マーシャリングを使用--zero-copy
するようにジェネレーターに指示した場合にのみ、文字列に必要です。
これは、 プロパティが プロパティではなく または assign
プロパティとしてretain
宣言されているObjective-C場合にcopy
必要です。 これらは通常、開発者によって間違って "最適化" されたサード パーティ製ライブラリで発生します。 一般に、 retain
または のユーザー派生クラスNSString
は、ライブラリ コードの知識なしに文字列の内容を変更し、アプリケーションを微妙に壊す可能性があるためNSMutableString
、プロパティassign
NSString
が正しくありません。 通常、これは早期の最適化が原因で発生します。
の 2 つのそのようなプロパティを次に Objective-C示します。
@property(nonatomic,retain) NSString *name;
@property(nonatomic,assign) NSString *name2;
DisposeAttribute
クラスに を [DisposeAttribute]
適用する場合は、クラスのメソッド実装に Dispose()
追加されるコード スニペットを指定します。
Dispose
メソッドは および btouch-native
ツールによってbmac-native
自動的に生成されるため、 属性を[Dispose]
使用して、生成されたDispose
メソッド実装にコードを挿入する必要があります。
次に例を示します。
[BaseType (typeof (NSObject))]
[Dispose ("if (OpenConnections > 0) CloseAllConnections ();")]
interface DatabaseConnection {
}
ExportAttribute
属性は [Export]
、ランタイムに公開されるメソッドまたはプロパティにフラグを設定するために Objective-C 使用されます。 この属性は、バインド ツールと、実際の Xamarin.iOS および Xamarin.Mac ランタイムの間で共有されます。 メソッドの場合、パラメーターは生成されたコードに逐語的に渡されます。プロパティの場合、getter と setter Exports は基本宣言に [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; }
}
セレクターは、バインドされている基になる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
必要があります。 静的ライブラリをリンクする場合は、 パラメーターとして をlibraryName
使用__Internal
します。
生成されるプロパティは常に静的です。
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# でフラグを設定キーワード (keyword)、生成されたアセンブリ内のコードに対してのみコードにアクセスできるようにする効果があります。 これは通常、レベルが低すぎる 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
の署名のみがサポートされていますが (バインドを使用するアプリのネイティブ リンクが不足しているmonotouch__objc_msgSendシンボルで失敗した場合に署名がサポートされていない場合はわかります)、 要求に応じてさらに追加できます。
NewAttribute
この属性は、ジェネレーターが宣言の前にキーワード (keyword)をnew
生成するために、メソッドとプロパティに適用されます。
これは、基底クラスに既に存在するサブクラスで同じメソッドまたはプロパティ名が導入された場合に、コンパイラの警告を回避するために使用されます。
NotificationAttribute
この属性をフィールドに適用して、ジェネレーターに厳密に型指定されたヘルパー Notifications クラスを生成させることができます。
この属性は、ペイロードを含まない通知の引数なしで使用することも、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!");
});
または、観察する特定のオブジェクトを設定します。 このメソッドにをobjectToObserve
渡null
すと、他のピアと同じように動作します。
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; }
}
上記では、 プロパティと ScreenY
プロパティをMyScreenChangedEventArgs
ScreenX
持つクラスが生成されます。このクラスは、それぞれキーScreenXKey
を使用して NSNotification.UserInfo ディクショナリからデータをフェッチし、ScreenYKey
適切な変換を適用します。 属性は [ProbePresence]
、値を抽出する代わりに、 で UserInfo
キーが設定されている場合にジェネレーターがプローブするために使用されます。 これは、キーの存在が値 (通常はブール値の場合) である場合に使用されます。
これにより、次のようなコードを記述できます。
var token = MyClass.NotificationsObserveScreenChanged ((notification) => {
Console.WriteLine ("The new screen dimensions are {0},{1}", notification.ScreenX, notification.ScreenY);
});
場合によっては、ディクショナリで渡される値に関連付けられた定数が存在しません。 Apple ではパブリック シンボル定数を使用する場合もあれば、文字列定数を使用する場合もあります。 既定では、 [Export]
指定した EventArgs
クラスの 属性では、指定した名前がパブリック シンボルとして使用され、実行時に参照されます。 そうでない場合は、代わりに文字列定数として検索し、値を 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
この属性を使用して、この特定のメソッドのバインドにキーワード (keyword)でフラグを設定する必要があることをバインド ジェネレーターに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))]
[Since (4,0)]
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 のシナリオについては、 このバグに関する説明を参照してください。
RetainListAttribute
パラメーターへのマネージド参照を保持するか、パラメーターへの内部参照を削除するようにジェネレーターに指示します。 これは、オブジェクトの参照を維持するために使用されます。
構文:
public class RetainListAttribute: Attribute {
public RetainListAttribute (bool doAdd, string listName);
}
の doAdd
値が true の場合、 パラメーターが に __mt_{0}_var List<NSObject>;
追加されます。 は {0}
、指定 listName
された に置き換えられます。 このバッキング フィールドは、API に対する補完的な部分クラスで宣言する必要があります。
例については、「foundation.cs」と「NSNotificationCenter.cs」を参照してください。
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]
厳密に型指定されたオブジェクトで弱く型指定されたオブジェクトをラップします。 これは主Objective-Cに、型または NSObject
としてid
宣言されるデリゲート オブジェクトで実行されます。 Xamarin.iOS と Xamarin.Mac で使用される規則は、これらのデリゲートまたはデータ ソースを型 NSObject
として公開し、規則 "Weak" と公開されている名前を使用して名前を付けます。 の id delegate
Objective-C プロパティは、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# の型システムを利用し、オーバーライド キーワード (keyword)を使用して意図を宣言しており、ユーザーのバインドでこの作業を行ったので、 を使用してメソッド[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 == null ? null : options.Dictionary")]
void Playback (string fileName, XyzOptions options);
}
属性で [Wrap]
修飾された [Category]
型内のメソッドに属性を適用する場合は、拡張メソッドが生成されるため、最初の引数として を含める This
必要があります。 次に例を示します。
[Wrap ("Write (This, image, options?.Dictionary, out error)")]
bool Write (CIImage image, CIImageRepresentationOptions options, out NSError error);
によって[Wrap]
生成されるメンバーは既定では行われませんvirtual
。メンバーが必要な場合は、省略可能isVirtual
なvirtual
パラメーターに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]
使用して、パラメーターを として渡す代わりに、文字列を C 文字列として渡すようにバインド ジェネレーターに NSString
指示できます。
ほとんどの Objective-C API はパラメーターを使用NSString
しますが、一部の API ではバリエーションではなく、文字列を渡すための API がNSString
公開char *
されています。
このような場合は を使用 [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; }
}
RetainListAttribute
パラメーターへのマネージド参照を保持するか、パラメーターへの内部参照を削除するようにジェネレーターに指示します。 これは、オブジェクトの参照を維持するために使用されます。
構文:
public class RetainListAttribute: Attribute {
public RetainListAttribute (bool doAdd, string listName);
}
の doAdd
値が true の場合、 パラメーターが に __mt_{0}_var List<NSObject>
追加されます。 は {0}
、指定 listName
された に置き換えられます。 このバッキング フィールドは、API に対する補完的な部分クラスで宣言する必要があります。
例については、「foundation.cs」と「NSNotificationCenter.cs」を参照してください。
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
定数の間に 2 つの方法変換メソッドを含む静的型も作成*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:]
使用して適用されるか、 属性や [Since]
属性などの任意の場所で[Lion]
使用できます。
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
バインドされているライブラリに(および UIKit
以外Foundation
の) フレームワークに対するハード要件がある場合は、 プロパティをFrameworks
、必要なプラットフォーム フレームワークのスペース区切りリストを含む文字列に設定する必要があります。 たとえば、 と を必要CoreGraphics
とするライブラリをバインドする場合は、 プロパティを Frameworks
に"CoreGraphics CoreText"
設定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 例外処理ライブラリが必要な場合は、このプロパティを true に設定します (gcc_eh)
LinkWithAttribute.SmartLink
SmartLink
Xamarin.iOS が必要かどうかをForceLoad
判断できるようにするには、 プロパティを true に設定する必要があります。
LinkWithAttribute.WeakFrameworks
プロパティは WeakFrameworks
プロパティと Frameworks
同じように動作しますが、リンク時 -weak_framework
に指定子が一覧表示されているフレームワークごとに gcc に渡される点が除きます。
WeakFrameworks
を使用すると、ライブラリとアプリケーションがプラットフォーム フレームワークと弱くリンクできるため、使用可能な場合は必要に応じて使用できますが、ライブラリにハード依存関係を持たないようにすることができます。これは、ライブラリが新しいバージョンの iOS に追加機能を追加する場合に役立ちます。 弱いリンクの詳細については、弱いリンク に関する Apple のドキュメントを参照してください。
弱いリンクの適切な候補はFrameworks
、アカウント、CoreBluetooth
CoreImage
、GLKit
NewsstandKit
および Twitter
のようになります。iOS 5 でのみ使用できるためです。
SinceAttribute (iOS) と LionAttribute (macOS)
属性を [Since]
使用して、API に特定の時点で導入されたものとしてフラグを設定します。 属性は、基になるクラス、メソッド、またはプロパティが使用できない場合にランタイムの問題を引き起こす可能性がある型とメソッドにフラグを設定するためにのみ使用する必要があります。
構文:
public SinceAttribute : Attribute {
public SinceAttribute (byte major, byte minor);
public byte Major, Minor;
}
一般に、列挙型、制約、または新しい構造体には適用しないでください。古いバージョンのオペレーティング システムを持つデバイスで実行された場合、ランタイム エラーは発生しないためです。
型に適用される例:
// Type introduced with iOS 4.2
[Since (4,2)]
[BaseType (typeof (UIPrintFormatter))]
interface UIViewPrintFormatter {
[Export ("view")]
UIView View { get; }
}
新しいメンバーに適用される例:
[BaseType (typeof (UIViewController))]
public interface UITableViewController {
[Export ("tableView", ArgumentSemantic.Retain)]
UITableView TableView { get; set; }
[Since (3,2)]
[Export ("clearsSelectionOnViewWillAppear")]
bool ClearsSelectionOnViewWillAppear { get; set; }
属性は [Lion]
同じ方法で適用されますが、Lion で導入された型にも適用されます。 iOS で使用されるより具体的なバージョン番号と比較して使用 [Lion]
する理由は、iOS が頻繁に改訂されるのに対し、OS X のメジャー リリースはまれに発生し、バージョン番号よりもコード名でオペレーティング システムを覚える方が簡単であるためです。
AdviceAttribute
この属性を使用して、開発者が使用する方が便利な他の API に関するヒントを開発者に提供します。 たとえば、厳密に型指定されたバージョンの API を指定する場合は、弱く型指定された属性でこの属性を使用して、開発者をより適切な API に誘導できます。
この属性の情報はドキュメントに示されており、改善方法に関するユーザーの提案を提供するためにツールを開発できます
RequiresSuperAttribute
これは、 属性の [Advice]
特殊化されたサブクラスであり、メソッドをオーバーライドするには、基本 (オーバーライドされた) メソッドの呼び出しが 必要 であることを開発者に示唆するために使用できます。
これは に対応します。 clang
__attribute__((objc_requires_super))
ZeroCopyStringsAttribute
Xamarin.iOS 5.4 以降でのみ使用できます。
この属性は、この特定のライブラリのバインド (で適用されている場合) または型で [assembly:]
高速ゼロ コピー文字列マーシャリングを使用するようにジェネレーターに指示します。 この属性は、コマンド ライン オプション --zero-copy
をジェネレーターに渡すことと同じです。
文字列にゼロ コピーを使用する場合、ジェネレーターでは、新しいNSString
オブジェクトの作成が発生せず、C# 文字列から文字列へのデータのコピーを回避することなく、使用するObjective-C文字列と同じ C# 文字列を効果的にObjective-C使用します。 ゼロ コピー文字列を使用する唯一の欠点は、ラップする文字列プロパティに 属性が設定されているか、または copy
としてretain
フラグが設定されていることを確認する[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
クラスは の文字列プロパティ Name
を生成し、 をディクショナリのキーとして使用 MyOptionKeys.NameKey
して文字列を取得します。 では、 をディクショナリのキーとして使用 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 |
Boolean に格納されます。 NSNumber |
列挙値 | に格納されている整数 NSNumber |
int |
に格納されている 32 ビット整数 NSNumber |
uint |
に格納されている 32 ビット符号なし整数 NSNumber |
nint |
NSInteger に格納されます。 NSNumber |
nuint |
NSUInteger に格納されます。 NSNumber |
long |
に格納されている 64 ビット整数 NSNumber |
float |
として格納される 32 ビット整数 NSNumber |
double |
として格納される 64 ビット整数 NSNumber |
NSObject サブクラスと サブクラス |
NSObject |
NSDictionary |
NSDictionary |
string |
NSString |
NSString |
NSString |
の C# Array NSObject |
NSArray |
列挙の C# Array |
NSArray 値を NSNumber 含む |