- 07/12/2017
- 4 luettavat minuutit
-
-
d
-
d
-
C
-
a
-
Objective-C-kieli perustuu valitsimiin. Valitsin on amessage, joka voidaan lähettää objektiin tai luokkaan. Xamarinia.iOS maps instance selectorsto instance menetelmiä, ja luokan valitsimet staattisia menetelmiä.
toisin kuin normaalit C-funktiot (ja kuten C++-jäsenfunktiot), et voi suoraan kutsua valitsinta käyttäen P/Invoke-toimintoa,vaan valitsimet lähetetään Objective-C-luokkaan tai instanssiin käyttäenobjc_msgSend
– funktiota.
lisätietoja Objectsguiden viesteistä löytyy Applen työskentelystä Objectsguiden kanssa.
esimerkki
Oletetaan, että haluat vedotasizeWithFont:forWidth:lineBreakMode:
valitsimeen NSString
.Ilmoitus (Applen dokumentaatiosta) on:
- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode
tällä API: lla on seuraavat ominaisuudet:
- Palautustyyppi on
CGSize
Unified API: lle. -
font
parametri on NSObject-projektista johdettu Uifontti (ja tyyppi (epäsuorasti), joka on yhdistetty systeemiin.IntPtr. -
width
parametri aCGFloat
on merkitty arvoonnfloat
. -
lineBreakMode
parametri, aUILineBreakMode
,on jo sitoutunut Xamariiniin.iOSUILineBreakMode
luettelona.
kaiken yhteen laskettuna objc_msgSend
julistuksen tulisi täsmätä:
CGSize objc_msgSend( IntPtr target, IntPtr selector, IntPtr font, nfloat width, UILineBreakMode mode);
ilmoittaa sen seuraavasti:
static extern CGSize cgsize_objc_msgSend_IntPtr_float_int ( IntPtr target, IntPtr selector, IntPtr font, nfloat width, UILineBreakMode mode);
voit kutsua tätä menetelmää, käytä koodia, kuten seuraavat:
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);
jos palautettu arvo olisi ollut alle 8 tavun kokoinen rakenne (kuten vanhempi SizeF
, jota käytettiin ennen yhdistettyihin sovellusliittymiin siirtymistä), yllä oleva koodi olisi toiminut simulaattorissa, mutta kaatunut laitteeseen. Jos haluat kutsua valitsinta, joka palauttaa arvon alle 8 bittiä, ilmoita funktio 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);
voit kutsua tätä menetelmää, käytä koodia, kuten seuraavat:
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 );
valitsijan kutsuminen
valitsijan kutsuminen on kolmivaiheista:
- Hakekaa valintakohde.
- Hanki valitsimen nimi.
- Soita
objc_msgSend
asianmukaisin perustein.
Valintakohteet
Valintakohde on joko objekti-instanssi tai Objective-C-luokka. Jos kohde on instanssi ja tuli sidotusta Xamarinista.iOS-Tyyppi, käytä ominaisuutta ObjCRuntime.INativeObject.Handle
.
jos kohde on luokka, käytä ObjCRuntime.Class
saadaksesi viittauksen luokkatasoon, käytä Class.Handle
ominaisuutta.
valitsijoiden nimet
valitsijoiden nimet on lueteltu Applen dokumenteissa. Esimerkiksi NSString
sisältää sizeWithFont:
ja sizeWithFont:forWidth:lineBreakMode:
valitsijat. Upotetut ja perään johtavat pylväät ovat osa valitsimen nimeä, eikä niitä voi jättää pois.
kun sinulla on valitsijan nimi, voit luoda sille ObjCRuntime.Selector
– instanssin.
soittaminen objc_msgSend
objc_msgSend
lähettää viestin (valitsin) objektille. Tämä perhe offunctions kestää vähintään kaksi vaadittua argumenttia: valitsin kohde (aninstance tai luokan kahva), valitsin itse, ja kaikki argumentit tarvitaan valitsin. Instanssin ja valitsimen argumenttien on oltavaSystem.IntPtr
, ja kaikkien jäljellä olevien argumenttien on vastattava tyyppiä, jonka selector odottaa, esimerkiksi nint
an int
, taiSystem.IntPtr
kaikille NSObject
johdetuille tyypeille. KäytäNSObject.Handle
ominaisuutta saadaksesi IntPtr
Objective-C-tyypin ilmentymälle.
on useampi kuin yksi objc_msgSend
funktio:
- käytä
objc_msgSend_stret
valitsijoille, jotka palauttavat struktin. ARM, tämä sisältää kaikki returntypes jotka eivät ole luettelo tai jokin C sisäänrakennettu tyypit (char
,short
,int
,long
,float
,double
). X86: ssa (simulaattorissa) tätä menetelmää on käytettävä kaikille rakenteille, jotka ovat kooltaan yli 8 tavua (CGSize
on 8 tavua eikä käytäobjc_msgSend_stret
simulaattorissa). - käytä
objc_msgSend_fpret
niitä valitsimia varten, jotka palauttavat liukulukuarvon vain x86: ssa. Tätä toimintoa ei tarvitse käyttää käsivarteen, vaan käytäobjc_msgSend
. - pääobjc_msgsendfunction on käytössä kaikilla muilla valitsimilla.
kun olet päättänyt, mille objc_msgSend
funktioille sinun on soitettava(simulaattori ja laite voivat kumpikin vaatia eri menetelmää), voit käyttää normaalia menetelmää funktion ilmoittamiseksi myöhempää kutsumista varten.
joukko valmiiksi tehtyjä objc_msgSend
julistuksia löytyyObjCRuntime.Messaging
.
erilaisia simulaattorilla ja laitteella tehtäviä invokaatioita
kuten edellä on kuvattu, Objective-C: llä on kolmenlaisia objc_msgSend
menetelmiä: yksi säännöllisille invokaatioille, yksi invokaatioille, jotka returnfloating point values (vain x86), ja yksi invokaatioille, jotka returnstruct values. Jälkimmäinen sisältää loppuliitteen _stret
inObjCRuntime.Messaging
.
jos vedotaan menetelmään, joka palauttaa tietyt struktuurit (jäljempänä kuvatut säännöt), on käytettävä menetelmää, jonka palautusarvo on ensimmäinen parametri out
arvona:
// The following returns a PointF structure:PointF ret;Messaging.PointF_objc_msgSend_stret_PointF_IntPtr (out ret, this.Handle, selConvertPointFromWindow.Handle, point, window.Handle);
sääntö siitä, milloin _stret_
– menetelmää tulee käyttää, eroaa x86: lla ja käsivarrella.Jos haluat sidosten toimivan sekä simulaattorissa että laitteessa,lisää esimerkiksi seuraava koodi:
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);}
käyttämällä objc_msgSend_stret-menetelmää
kun rakennetaan ARM-järjestelmää varten, käytetäänobjc_msgSend_stret
mitä tahansa arvotyyppiä, joka ei ole arvojoukko tai jokin perusjoukko (int
, byte
, short
, long
, double
, float
).
rakennettaessa x86: ta varten käytetäänobjc_msgSend_stret
mitä tahansa arvotyyppiä, joka ei ole arvojoukko tai mikä tahansa arvojoukon perustyyppi (int
, byte
, short
, long
, double
, float
)ja jonka alkuperäinen koko on suurempi kuin 8 tavua.
omien allekirjoitusten luominen
seuraavia tietoja voidaan käyttää omien allekirjoitusten luomiseen tarvittaessa.