XamarinのObjective-Cセレクタ。イオス

  • 07/12/2017
  • 4 読むべき分
    • d
    • d
    • c
    • a

Objective-C言語はセレクタに基づいています。 セレクタは、オブジェクトまたはクラスに送信できるamessageです。 Xamarin。iOSは、インスタンスselectorstoインスタンスメソッド、およびクラスセレクタを静的メソッドにマッ

通常のC関数(およびC++メンバー関数のような)とは異なり、代わりにp/Invokeを使用してセレクタを直接呼び出すことはできません。objc_msgSend関数を使用してセレクタをObjective-Cクラスまたはインスタンスに送信します。

Objective-Cのメッセージの詳細については、AppleのObjectsguideでの作業を見てみましょう。

NSStringsizeWithFont:forWidth:lineBreakMode:セレクタを呼び出したいとします。宣言(Appleのドキュメントから)は次のとおりです:

- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode

このAPIには、次の特性があります:

  • 統合APIの戻り値の型はCGSizeです。
  • fontパラメータはUIFont(およびNSObjectから派生した(間接的に)型であり、Systemにマップされます。IntPtr。
  • widthパラメータaCGFloatnfloatにマップされます。
  • lineBreakModeパラメーターであるUILineBreakModeは、Xamarinで既にバインドされています。iosをUILineBreakMode列挙体として使用します。

すべてをまとめると、objc_msgSend宣言が一致する必要があります:

CGSize objc_msgSend( IntPtr target, IntPtr selector, IntPtr font, nfloat width, UILineBreakMode mode);

次のように宣言します:

static extern CGSize cgsize_objc_msgSend_IntPtr_float_int ( IntPtr target, IntPtr selector, IntPtr font, nfloat width, UILineBreakMode mode);

このメソッドを呼び出すには、次のようなコードを使用します:

NSString target = ...Selector selector = new Selector ("sizeWithFont:forWidth:lineBreakMode:");UIFont font = ...nfloat width = ...UILineBreakMode mode = ...CGSize size = cgsize_objc_msgSend_IntPtr_float_int( target.Handle, selector.Handle, font == null ? IntPtr.Zero : font.Handle, width, mode);

戻り値が8バイト未満の構造体であった場合(統合Apiに切り替える前に使用された古いSizeFのように)、上記のコードはシミュレータで実行されますが、デバ サイズが8ビット未満の値を返すセレクタを呼び出すには、objc_msgSend_stret関数を宣言します:

static extern void cgsize_objc_msgSend_stret_IntPtr_float_int ( out CGSize retval, IntPtr target, IntPtr selector, IntPtr font, nfloat width, UILineBreakMode mode);

このメソッドを呼び出すには、次のようなコードを使用します:

NSString target = ...Selector selector = new Selector ("sizeWithFont:forWidth:lineBreakMode:");UIFont font = ...nfloat width = ...UILineBreakMode mode = ...CGSize size;if (Runtime.Arch == Arch.SIMULATOR) size = cgsize_objc_msgSend_IntPtr_float_int( target.Handle, selector.Handle, font == null ? IntPtr.Zero : font.Handle, width, mode );else cgsize_objc_msgSend_stret_IntPtr_float_int( out size, target.Handle, selector.Handle, font == null ? IntPtr.Zero: font.Handle, width, mode );

セレクタを呼び出す

セレクタを呼び出すには、次の三つのステップがあります:

  1. セレクタターゲットを取得します。
  2. セレクタ名を取得します。
  3. 適切な引数を指定してobjc_msgSendを呼び出します。

セレクタターゲット

セレクタターゲットは、オブジェクトインスタンスまたはObjective-Cクラスのいずれかです。 ターゲットがインスタンスであり、バインドされたXamarinから来た場合。iOSタイプでは、ObjCRuntime.INativeObject.Handleプロパティを使用します。

ターゲットがクラスの場合は、ObjCRuntime.Classを使用してclassinstanceへの参照を取得し、Class.Handleプロパティを使用します。

セレクタ名

セレクタ名はAppleのドキュメントに記載されています。 たとえば、NSStringにはsizeWithFont:およびsizeWithFont:forWidth:lineBreakMode:セレクタが含まれます。 埋め込まれたコロンと末尾のコロンはセレクタ名の一部であり、省略することはできません。

セレクタ名を取得したら、そのインスタンスのObjCRuntime.Selectorインスタンスを作成できます。

objc_msgsend

objc_msgSendを呼び出すと、オブジェクトにメッセージ(セレクタ)が送信されます。 このファミリoffunctionsは、少なくとも二つの必須引数を取ります:セレクタターゲット(aninstanceまたはクラスハンドル)、セレクタ自体、およびセレクタに必要な任意のargumentsrequired。 インスタンス引数とセレクタ引数はSystem.IntPtrでなければならず、残りのすべての引数は、intの場合はnintNSObjectから派生したすべての型の場合はSystem.IntPtrと一致する必要が Objective-C型インスタンスのIntPtrを取得するには、NSObject.Handleプロパティを使用します。

複数のobjc_msgSend機能があります:

  • 構造体を返すセレクタにはobjc_msgSend_stretを使用します。 ARMでは、これには列挙型でもCの組み込み型でもないすべてのreturntypesが含まれます(char,short, int, long, float, double). X86(シミュレータ)では、thismethodはサイズが8バイトを超えるすべての構造体に使用する必要があります(CGSizeは8バイトであり、thesimulatorではobjc_msgSend_stretを使用しません)。
  • x86でのみ浮動小数点値を返すセレクタにはobjc_msgSend_fpretを使用します。 この関数はARMで使用する必要はありません。objc_msgSendを使用してください。
  • mainobjc_msgsend関数は、他のすべてのセレクタに使用されます。

どのobjc_msgSend関数を呼び出す必要があるかを決定したら(シミュレータとデバイスにはそれぞれ異なるメソッドが必要な場合があります)、通常のメソッドを使用して、後の呼び出しのために関数を宣言できます。

既製のobjc_msgSend宣言のセットはObjCRuntime.Messagingにあります。

シミュレータとデバイス上の異なる呼び出し

上記のように、Objective-Cには、通常の呼び出し、ポイント値を返す呼び出し(x86のみ)、およびstruct値を返す呼び出しの3種類のobjc_msgSendメソッドがあります。 後者はObjCRuntime.Messagingに接尾辞_stretを含みます。

特定の構造体(以下に説明するrulesdescribed)を返すメソッドを呼び出す場合は、戻り値をfirstparameterとしてout値としてメソッドを呼び出す必要があります:

// The following returns a PointF structure:PointF ret;Messaging.PointF_objc_msgSend_stret_PointF_IntPtr (out ret, this.Handle, selConvertPointFromWindow.Handle, point, window.Handle);

_stret_メソッドを使用する場合のルールは、x86とARMで異なります。シミュレータとデバイスの両方でバインディングを動作させたい場合は、次のようなコードを追加します:

if (Runtime.Arch == Arch.DEVICE){ PointF ret; Messaging.PointF_objc_msgSend_stret_PointF_IntPtr (out ret, myHandle, selector.Handle); return ret;}else{ return Messaging.PointF_objc_msgSend_PointF_IntPtr (myHandle, selector.Handle);}

OBJC_msgsend_stretメソッド

の使用ARM用にビルドするときは、列挙型ではない値型または列挙型の基本型のいずれかにobjc_msgSend_stretを使用します(int, byte, short, long, double, float).

x86用にビルドするときは、列挙型ではない値型または列挙型の基本型のいずれかにobjc_msgSend_stretを使用します(int, byte, short, long, double, float)そして、そのネイティブサイズは8バイトよりも大きいです。

独自の署名の作成

必要に応じて、以下の要点を使用して独自の署名を作成することができます。

コメントを残す

メールアドレスが公開されることはありません。