Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Die Objective-C Sprache basiert auf Selektoren. Ein Selektor ist eine Nachricht, die an ein Objekt oder eine Klasse gesendet werden kann. Xamarin.iOS ordnet instance Selektoren instance Methoden und Klassenselektoren statischen Methoden zu.
Im Gegensatz zu normalen C-Funktionen (und wie C++-Memberfunktionen) können Sie einen Selektor nicht direkt mit P/Invoke aufrufen. Selektoren werden stattdessen mithilfe von an eine Objective-C Klasse oder instance gesendet.objc_msgSend Funktion.
Weitere Informationen zu Nachrichten in finden Sie im Objective-CLeitfaden arbeiten mit Objekten von Apple.
Beispiel
Angenommen, Sie möchten diesizeWithFont:forWidth:lineBreakMode: -Auswahl auf NSString.
Die Erklärung (aus der Apple-Dokumentation) lautet:
- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode
Diese API weist die folgenden Merkmale auf:
- Der Rückgabetyp ist
CGSizefür die einheitliche API. - Der
fontParameter ist ein UIFont (und ein (indirekt) von NSObject abgeleiteter Typ und wird System.IntPtr zugeordnet. - Der
width-Parameter wirdCGFloatzugeordnetnfloat. - Der
lineBreakMode-Parameter wurdeUILineBreakModebereits in Xamarin.iOS als gebunden.UILineBreakModeEnumeration.
Die Deklaration sollte zusammen mit folgenden objc_msgSend Übereinstimmungen übereinstimmen:
CGSize objc_msgSend(
IntPtr target,
IntPtr selector,
IntPtr font,
nfloat width,
UILineBreakMode mode
);
Deklarieren Sie sie wie folgt:
[DllImport (Constants.ObjectiveCLibrary, EntryPoint="objc_msgSend")]
static extern CGSize cgsize_objc_msgSend_IntPtr_float_int (
IntPtr target,
IntPtr selector,
IntPtr font,
nfloat width,
UILineBreakMode mode
);
Verwenden Sie code wie den folgenden, um diese Methode aufzurufen:
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
);
Wäre der zurückgegebene Wert eine Struktur von weniger als 8 Bytes groß (wie die ältere SizeF , die vor dem Wechsel zu den einheitlichen APIs verwendet wurde), wäre der obige Code im Simulator ausgeführt worden, aber auf dem Gerät abgestürzt. Um einen Selektor aufzurufen, der einen Wert zurückgibt, der weniger als 8 Bits groß ist, deklarieren Sie die objc_msgSend_stret Funktion:
[DllImport (MonoTouch.Constants.ObjectiveCLibrary, EntryPoint="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
);
Verwenden Sie code wie den folgenden, um diese Methode aufzurufen:
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
);
Aufrufen eines Selektors
Das Aufrufen eines Selektors umfasst drei Schritte:
- Rufen Sie das Selektorziel ab.
- Rufen Sie den Selektornamen ab.
- Rufen Sie
objc_msgSendmit den entsprechenden Argumenten auf.
Selektorziele
Ein Selektorziel ist entweder ein Objekt instance oder eine Objective-C Klasse. Wenn das Ziel ein instance ist und von einem gebundenen Xamarin.iOS-Typ stammt, verwenden Sie die ObjCRuntime.INativeObject.Handle -Eigenschaft.
Wenn das Ziel eine Klasse ist, verwenden Sie ObjCRuntime.Class , um einen Verweis auf die Klasse instance abzurufen, und verwenden Sie dann die Class.Handle -Eigenschaft.
Selektornamen
Selektornamen sind in der Apple-Dokumentation aufgeführt. Enthält sizeWithFont: z. NSString B. und sizeWithFont:forWidth:lineBreakMode: Selektoren. Die eingebetteten und nachfolgenden Doppelpunkte sind Teil des Selektornamens und können nicht weggelassen werden.
Sobald Sie über einen Selektornamen verfügen, können Sie eine ObjCRuntime.Selector instance dafür erstellen.
Aufrufen von objc_msgSend
objc_msgSend sendet eine Nachricht (Selektor) an ein -Objekt. Diese Funktionsfamilie akzeptiert mindestens zwei erforderliche Argumente: das Selektorziel (ein instance- oder Klassenhandle), den Selektor selbst und alle argumente, die für den Selektor erforderlich sind. Die argumente instance und selektor müssen seinSystem.IntPtr, und alle verbleibenden Argumente müssen mit dem Typ übereinstimmen, den der Selektor erwartet, z. B. ein nint für ein intoder ein System.IntPtr für alle NSObjectabgeleiteten Typen. Verwenden Sie die SchaltflächeNSObject.Handle-Eigenschaft zum Abrufen eines IntPtr für einen Objective-C Typ instance.
Es gibt mehrere objc_msgSend Funktionen:
- Verwenden Sie
objc_msgSend_stretfür Selektoren, die eine Struktur zurückgeben. In ARM umfasst dies alle Rückgabetypen, die keine Enumeration sind, oder einen der integrierten C-Typen (char, ,intshort,longfloat, ,double). Auf x86 (dem Simulator) muss diese Methode für alle Strukturen verwendet werden, die größer als 8 Bytes sind (CGSizeist 8 Bytes und wird im Simulator nicht verwendetobjc_msgSend_stret). - Verwenden Sie nur
objc_msgSend_fpretfür Selektoren, die einen Gleitkommawert für x86 zurückgeben. Diese Funktion muss nicht für ARM verwendet werden. Verwenden Sieobjc_msgSendstattdessen . - Die Standard objc_msgSend-Funktion wird für alle anderen Selektoren verwendet.
Nachdem Sie entschieden haben, welche objc_msgSend Funktionen Sie aufrufen müssen (Simulator und Gerät erfordern möglicherweise jeweils eine andere Methode), können Sie eine normale [DllImport] Methode verwenden, um die Funktion für den späteren Aufruf zu deklarieren.
Eine Reihe von vordefinierten objc_msgSend Deklarationen finden Sie in ObjCRuntime.Messaging.
Verschiedene Aufrufe auf Simulator und Gerät
Wie oben beschrieben, Objective-C verfügt über drei Arten von objc_msgSend Methoden: eine für reguläre Aufrufe, eine für Aufrufe, die Gleitkommawerte zurückgeben (nur x86), und eine für Aufrufe, die Strukturwerte zurückgeben. Letzteres enthält das Suffix _stret in ObjCRuntime.Messaging.
Wenn Sie eine Methode aufrufen, die bestimmte Strukturen (unten beschriebene Regeln) zurückgibt, müssen Sie die -Methode mit dem Rückgabewert als ersten Parameter als Wert out aufrufen:
// The following returns a PointF structure:
PointF ret;
Messaging.PointF_objc_msgSend_stret_PointF_IntPtr (out ret, this.Handle, selConvertPointFromWindow.Handle, point, window.Handle);
Die Regel für die Verwendung der _stret_ -Methode unterscheidet sich bei x86 und ARM.
Wenn Ihre Bindungen sowohl auf dem Simulator als auch auf dem Gerät funktionieren sollen, fügen Sie Code wie den folgenden hinzu:
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);
}
Verwenden der objc_msgSend_stret-Methode
Verwenden Sie beim Erstellen für ARM dieobjc_msgSend_stretfür jeden Werttyp, der keine Enumeration ist, oder einen der Basistypen für eine Enumeration (int, , shortbyte, longdouble, , float).
Verwenden Sie beim Erstellen für x86objc_msgSend_stretfür jeden Werttyp, der keine Enumeration ist, oder einen der Basistypen für eine Enumeration (int, , shortbyte, long, doublefloat) und deren systemeigene Größe größer als 8 Byte ist.
Erstellen eigener Signaturen
Der folgende Gist kann verwendet werden, um bei Bedarf eigene Signaturen zu erstellen.