- 07/12/2017
- 4 minuten om te lezen
-
-
d
-
d
-
c
-
a
-
de Objective-C taal is gebaseerd op selectors. Een selector is een bericht dat kan worden verzonden naar een object of een klasse. Xamarin.iOS wijst instance selectors toe aan instance methods, en class selectors aan statische methoden.
in tegenstelling tot normale C-functies (en zoals C++ – member-functies), kunt u niet rechtstreeks een selector aanroepen met behulp van P/inroepen.in plaats daarvan worden selectors naar een Objective-C-klasse of instantie gestuurd met behulp van deobjc_msgSend
– functie.
voor meer informatie over berichten in Objective-C, Zie Apple ‘ sworking with objects Guide.
voorbeeld
stel dat u desizeWithFont:forWidth:lineBreakMode:
selector op NSString
wilt aanroepen.De verklaring (uit de documentatie van Apple) is:
- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode
deze API heeft de volgende kenmerken:
- het return type is
CGSize
voor de Unified API. - de
font
parameter is een UIFont (en een type (indirect) afgeleid van NSObject, en wordt toegewezen aan het systeem.IntPtr. - de parameter
width
, aCGFloat
, wordt toegewezen aannfloat
. - de parameter
lineBreakMode
, aUILineBreakMode
, is al gebonden in Xamarin.iOS als deUILineBreakMode
opsomming.
bij elkaar opgeteld moet de objc_msgSend
– declaratie overeenkomen met:
CGSize objc_msgSend( IntPtr target, IntPtr selector, IntPtr font, nfloat width, UILineBreakMode mode);
verklaart het als volgt::
static extern CGSize cgsize_objc_msgSend_IntPtr_float_int ( IntPtr target, IntPtr selector, IntPtr font, nfloat width, UILineBreakMode mode);
om deze methode aan te roepen, gebruik code zoals de volgende:
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);
als de geretourneerde waarde een structuur was die minder dan 8 bytes groot was (zoals de oudere SizeF
die werd gebruikt voor het overschakelen naar de Unified API ‘ s), zou de bovenstaande code op de simulator zijn uitgevoerd, maar op het apparaat zijn gecrasht. Als u een selector wilt aanroepen die een waarde van minder dan 8 bits retourneert, declareert u de functie 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);
om deze methode aan te roepen, gebruik code zoals de volgende:
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 );
een selector aanroepen
een selector aanroepen heeft drie stappen:
- haal het selectordoel.
- krijg de naam van de selector.
- Call
objc_msgSend
met de juiste argumenten.
selectordoelen
een selectordoel is een object-instantie of een object – C-klasse. Als het doel een instantie is en afkomstig is van een gebonden Xamarin.iOS-type, gebruik de eigenschap ObjCRuntime.INativeObject.Handle
.
als het doel een klasse is, gebruik dan ObjCRuntime.Class
om een verwijzing naar de classinstance te krijgen, gebruik dan de eigenschap Class.Handle
.
Selectornamen
Selectornamen worden vermeld in de documentatie van Apple. NSString
omvat bijvoorbeeld sizeWithFont:
en sizeWithFont:forWidth:lineBreakMode:
selectors. De ingebedde en achterliggende punten maken deel uit van de selectornaam en kunnen niet worden weggelaten.
Als u een selectornaam hebt, kunt u er een instance ObjCRuntime.Selector
voor maken.
het aanroepen van objc_msgSend
objc_msgSend
stuurt een bericht (selector) naar een object. Deze familie offunctions heeft ten minste twee vereiste argumenten: het selector doel (aninstance of class handle), de selector zelf, en alle argumenten vereist voor de selector. De instantie-en selectorargumenten moetenSystem.IntPtr
zijn, en alle overige argumenten moeten overeenkomen met het type dat de selector verwacht, bijvoorbeeld een nint
voor een int
, of eenSystem.IntPtr
voor alle NSObject
-afgeleide types. Gebruik de eigenschapNSObject.Handle
om een IntPtr
te verkrijgen voor een Objective-C type instantie.
er is meer dan één objc_msgSend
functie:
- gebruik
objc_msgSend_stret
voor selectors die een struct retourneren. Op ARM, dit omvat alle returntypes die geen opsomming of een van de C ingebouwde types zijn(char
,short
,int
,long
,float
,double
). Op x86 (de simulator) moet deze methode gebruikt worden voor alle structuren groter dan 8 bytes (CGSize
is 8 bytes en gebruiktobjc_msgSend_stret
niet in de simulator). - gebruik
objc_msgSend_fpret
voor selectors die alleen op x86 een drijvende-kommawaarde retourneren. Deze functie hoeft niet op ARM te worden gebruikt; gebruik in plaats daarvanobjc_msgSend
. - de functie mainobjc_msgsend wordt gebruikt voor alle andere selectors.
zodra u hebt besloten welke objc_msgSend
functie(s) u moet aanroepen (simulator en apparaat kunnen elk een andere methode vereisen), kunt u een normale methode gebruiken om de functie te declareren voor latere aanroep.
een reeks vooraf gemaakte objc_msgSend
verklaringen is te vinden inObjCRuntime.Messaging
.
verschillende aanroepingen op simulator en apparaat
zoals hierboven beschreven, heeft Objective-C drie soorten objc_msgSend
methoden: één voor regelmatige aanroepingen, één voor aanroepingen die zwevende puntwaarden retourneren (alleen x86), en één voor aanroepingen die waarden retourneren. Deze laatste bevat het achtervoegsel _stret
inObjCRuntime.Messaging
.
als u een methode aanroept die bepaalde struct ‘ s retourneert (regels hieronder beschreven), moet u de methode aanroepen met de retourwaarde als de firstparameter als een out
waarde:
// The following returns a PointF structure:PointF ret;Messaging.PointF_objc_msgSend_stret_PointF_IntPtr (out ret, this.Handle, selConvertPointFromWindow.Handle, point, window.Handle);
de regel voor het gebruik van de _stret_
methode verschilt op x86 en ARM.Als u wilt dat uw bindingen werken op zowel de simulator en het apparaat,voeg code zoals de volgende:
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);}
gebruik de objc_msgSend_stret-methode
gebruik bij het bouwen voor ARMobjc_msgSend_stret
voor elk waardetype dat geen Enumeratie is of een van de basistypen voor een enumeratie (int
, byte
, short
, long
, double
, float
).
gebruik bij het bouwen voor x86objc_msgSend_stret
voor elk waardetype dat geen Enumeratie is of een van de basistypen voor een enumeratie (int
, byte
, short
, long
, double
, float
)en waarvan de oorspronkelijke grootte groter is dan 8 bytes.
uw eigen handtekeningen aanmaken
de volgende kern kan worden gebruikt om uw eigen handtekeningen te maken, indien nodig.