- 07/12/2017
- 4 minutter å lese
-
-
d
-
d
-
c
-
a
-
Objective-C-språket er basert på velgere. En velger er amessage som kan sendes til et objekt eller en klasse. Xamarin.iOS maps instance selectorsto instans metoder, og klasse velgere til statiske metoder.
I Motsetning til vanlige c-funksjoner (og som c++ medlemsfunksjoner), kan du ikke direkte påkalle en velger ved hjelp av p/Påberope I Stedet,velgere sendes til En Objective-C-klasse eller forekomst ved hjelp av funksjonen objc_msgSend
.
for mer informasjon om meldinger I Objective-C, ta En titt På Apple ‘ working with Objectsguide.
Eksempel
Anta at du vil aktivere sizeWithFont:forWidth:lineBreakMode:
– velgeren på NSString
.Erklæringen (Fra Apples dokumentasjon) er:
- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode
DENNE API har følgende egenskaper:
- returtypen er
CGSize
for Enhetlig API. - parameteren
font
er En UIFont (og en type (indirekte) avledet Fra NSObject, og er tilordnet Til Systemet.IntPtr. - parameteren
width
, aCGFloat
, er tilordnet tilnfloat
. - parameteren
lineBreakMode
, aUILineBreakMode
, er allerede bundet I Xamarin.iOS somUILineBreakMode
– opplistingen.
Når du setter alt sammen, bør objc_msgSend
– erklæringen samsvare:
CGSize objc_msgSend( IntPtr target, IntPtr selector, IntPtr font, nfloat width, UILineBreakMode mode);
Erklære det som følger:
static extern CGSize cgsize_objc_msgSend_IntPtr_float_int ( IntPtr target, IntPtr selector, IntPtr font, nfloat width, UILineBreakMode mode);
for å ringe denne metoden, bruk kode som følgende:
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);
hadde den returnerte verdien vært en struktur som var mindre enn 8 byte i størrelse (som den eldre SizeF
brukt før du byttet til De Enhetlige Apiene), ville koden ovenfor ha kjørt på simulatoren, men krasjet på enheten. Hvis du vil kalle en velger som returnerer en verdi mindre enn 8 biter, erklærer du objc_msgSend_stret
– funksjonen:
static extern void cgsize_objc_msgSend_stret_IntPtr_float_int ( out CGSize retval, IntPtr target, IntPtr selector, IntPtr font, nfloat width, UILineBreakMode mode);
for å ringe denne metoden, bruk kode som følgende:
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 );
Å Påkalle en velger
Å Påkalle en velger har tre trinn:
- Hent velgermålet.
- Hent navnet på velgeren.
- Ring
objc_msgSend
med de riktige argumentene.
Velgermål
et velgermål er enten en objektforekomst eller En Objective-c-klasse. Hvis målet er en forekomst og kom fra en bundet Xamarin.iOS type, bruk egenskapen ObjCRuntime.INativeObject.Handle
.
hvis målet er en klasse, bruker du ObjCRuntime.Class
for å få en referanse til classinstance, og deretter bruker du egenskapen Class.Handle
.
Valgnavn er oppført I Apples dokumentasjon. NSString
inkluderer for eksempel sizeWithFont:
og sizeWithFont:forWidth:lineBreakMode:
velgere. De innebygde og etterfølgende kolonene er en del av velgernavnet og kan ikke utelates.
når du har et valgnavn, kan du opprette en ObjCRuntime.Selector
– forekomst for den.
Ringer objc_msgSend
objc_msgSend
sender en melding (velger) til et objekt. Denne family offunctions tar minst to nødvendige argumenter: velgermålet (aninstance eller klassehåndtaket), selve velgeren og eventuelle argumenter som kreves for velgeren. Forekomsten og velgerargumentene må væreSystem.IntPtr
, og alle gjenværende argumenter må samsvare med typen theselector forventer, for eksempel en nint
for en int
eller enSystem.IntPtr
for alle NSObject
– avledede typer. Bruk egenskapenNSObject.Handle
til å hente en IntPtr
for en Forekomst Av Objective-C-typen.
det er mer enn en objc_msgSend
funksjon:
- Bruk
objc_msgSend_stret
for velgere som returnerer en struct. PÅ ARM, dette inkluderer alle returntypes som ikke er en opplisting eller Noen Av c innebygde typer (char
,short
,int
,long
,float
,double
). På x86 (simulatoren) må dettemetoden brukes til alle strukturer som er større enn 8 byte i størrelse (CGSize
er 8 byte og bruker ikkeobjc_msgSend_stret
i simulatoren). - Bruk
objc_msgSend_fpret
for velgere som bare returnerer en flyttallsverdi på x86. Thisfunction trenger ikke å bli brukt PÅ ARM; i stedet brukerobjc_msgSend
. - mainobjc_msgSendfunction brukes for alle andre velgere.
når du har bestemt hvilken objc_msgSend
funksjon(er) du må ringe(simulator og enhet kan hver kreve en annen metode), kan du bruke en normal metode for å erklære funksjonen for senere påkalling.
et sett med pre-made objc_msgSend
erklæringer finnes iObjCRuntime.Messaging
.
Ulike besvergelser på simulator og enhet
Som beskrevet ovenfor har Objective-C tre typer objc_msgSend
metoder: en for vanlige besvergelser, en for besvergelser som returnerer punktverdier (kun x86), og en for besvergelser som returnerer verdier. Sistnevnte inkluderer suffikset _stret
iObjCRuntime.Messaging
.
hvis du påberoper en metode som vil returnere visse structs (rulesdescribed nedenfor), må du påberope metoden med returverdien som firstparameter som en out
– verdi:
// The following returns a PointF structure:PointF ret;Messaging.PointF_objc_msgSend_stret_PointF_IntPtr (out ret, this.Handle, selConvertPointFromWindow.Handle, point, window.Handle);
regelen for når du skal bruke _stret_
– metoden, er forskjellig på x86 og ARM.Hvis du vil at bindingene skal fungere på både simulatoren og enheten,legg til kode som følgende:
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);}
bruke metoden objc_msgSend_stret
når du bygger FOR ARM, bruker duobjc_msgSend_stret
for alle verdityper som ikke er en opplisting eller noen av grunntypene for en opplisting (int
, byte
, short
, long
, double
, float
).
når du bygger for x86, bruk objc_msgSend_stret
for alle verdityper som ikke er en opplisting eller noen av grunntypene for en opplisting (int
, byte
, short
, long
, double
, float
)og hvis opprinnelige størrelse er større enn 8 byte.
Opprette dine egne signaturer
følgende hovedpunkt kan brukes til å lage dine egne signaturer, om nødvendig.