Objective-C szelektorok Xamarinban.Iosz

  • 07/12/2017
  • 4 perc olvasni
    • d
    • d
    • c
    • a

az Objective-C nyelv a szelektorokon alapul. A választó amessage, amelyet el lehet küldeni egy objektumnak vagy egy osztálynak. Xamarin.az iOS leképezi a példányválasztókat a példánymódszerekre, az osztályválasztókat pedig a statikus módszerekre.

a normál C függvényektől eltérően (és a C++ tagfüggvényekhez hasonlóan) nem lehet közvetlenül meghívni egy választótp/meghívás ehelyett a választókat egy Objective-C osztályba vagy példányba küldi aobjc_msgSend függvény használatával.

az Objective-C üzenetekkel kapcsolatos további információkért tekintse meg az Apple objectsguide-ot.

példa

tegyük fel, hogy meg akarja hívni asizeWithFont:forWidth:lineBreakMode:választót NSString.A nyilatkozat (Az Apple dokumentációjából):

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

ez az API a következő jellemzőkkel rendelkezik:

  • a visszatérési típus CGSize az egységes API esetében.
  • a font paraméter egy Uifont (és egy Típus (közvetetten) az NSObject-ből származik, és a rendszerhez van hozzárendelve.IntPtr.
  • a width paraméter, a CGFloat, nfloat – re van leképezve.
  • a lineBreakModeparaméter, a UILineBreakMode, már kötött a Xamarin.iOS, mint aUILineBreakMode felsorolás.

mindent összevetve, a objc_msgSend nyilatkozatnak meg kell egyeznie:

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

állapítsa meg a következőképpen:

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

a módszer meghívásához használja a következő kódot:

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);

ha a visszaadott érték 8 bájtnál kisebb méretű struktúra lett volna (mint a régebbi SizeF, amelyet az egységes API-kra való váltás előtt használtak), a fenti kód a szimulátoron futott volna, de összeomlott az eszközön. Ha olyan választót szeretne meghívni, amely 8 bitnél kisebb értéket ad vissza, deklarálja a objc_msgSend_stret függvényt:

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

a módszer meghívásához használja a következő kódot:

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 );

a választó meghívása

a választó meghívása három lépésből áll:

  1. Szerezd meg a választó célt.
  2. Szerezd meg a választó nevét.
  3. hívja a objc_msgSend – et a megfelelő argumentumokkal.

választó célok

a választó cél vagy objektumpéldány, vagy Objective-C osztály. Ha a cél egy példány, és egy kötött Xamarinból származik.iOS Típus, használja a ObjCRuntime.INativeObject.Handle tulajdonságot.

ha a cél egy osztály, használja a ObjCRuntime.Class hivatkozást a classinstance-re, majd használja a Class.Handle tulajdonságot.

Választónevek

a Választóneveket az Apple dokumentációja tartalmazza. Például a NSString magában foglalja a sizeWithFont: és a sizeWithFont:forWidth:lineBreakMode: választókat. A beágyazott és záró kettőspontok a választó nevének részét képezik, és nem hagyhatók el.

ha megvan a választó neve, létrehozhat egy ObjCRuntime.Selector példányt.

Objc_msgsend hívása

objc_msgSend üzenetet (választót) küld egy objektumnak. Ez a család offfunkciók vesz legalább két szükséges érvek: a választó cél (aninstance vagy osztály fogantyú), a választó maga, és minden argumentsrequired a választó. A példány és a választó argumentumainakSystem.IntPtr – nek kell lenniük, és az összes fennmaradó argumentumnak meg kell egyeznie a theselector által elvárt típussal, például egy nint egy int-ra, vagy egySystem.IntPtr az összes NSObject – ből származó típusra. A NSObject.Handletulajdonsággal IntPtr értéket kaphat egy Objective-C típusú példányhoz.

egynél több objc_msgSend funkció van:

  • használja a objc_msgSend_stret – et olyan szelektorokhoz, amelyek visszaadják a struct-ot. Az ARM, ez magában foglalja az összes returntypes, amelyek nem egy felsorolás vagy a C beépített típusok (char,short, int, long, float, double). Az x86-on (a szimulátoron) ezt a módszert kell használni minden 8 bájtnál nagyobb méretű struktúrához (aCGSize 8 bájt, és nem használja a objc_msgSend_stret – et a szimulátorban).
  • használja a objc_msgSend_fpret értéket olyan választókhoz, amelyek lebegőpontos értéket adnak vissza csak x86-on. Ezt a funkciót nem kell használni az ARM-en; ehelyett használja objc_msgSend.
  • a mainobjc_msgSendfunction minden más választóhoz használható.

miután eldöntötte, hogy melyik objc_msgSendfüggvényt(függvényeket) kell hívnia(a szimulátorhoz és az eszközhöz eltérő módszerre lehet szükség), használhatja a normál módszert a függvény későbbi meghíváshoz történő deklarálásához.

az előre elkészített objc_msgSenddeklarációk halmaza megtalálható aObjCRuntime.Messaging -ben.

különböző invokációk a szimulátoron és az eszközön

a fent leírtak szerint az Objective-C háromféle objc_msgSendmódszert tartalmaz: az egyik a rendszeres invokációkhoz, az egyik a visszatérő pontértékekhez (csak x86), a másik pedig a returnstruct értékekhez. Ez utóbbi tartalmazza a _stret utótagotObjCRuntime.Messaging – ben.

ha olyan metódust hív meg, amely bizonyos struktúrákat (az alábbiakban ismertetett szabályokat) ad vissza, akkor a metódust kell meghívnia, amelynek visszatérési értéke az elsőparaméter out értékként:

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

a _stret_ módszer használatának szabálya eltér az x86 és az ARM esetében.Ha azt szeretné, hogy a kötések mind a szimulátoron,mind az eszközön működjenek, adjon hozzá az alábbi kódot:

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);}

az objc_msgSend_stret metódus használata

amikor arm-re épít, használja aobjc_msgSend_stret értéket minden olyan értéktípushoz, amely nem felsorolás, vagy a felsorolás egyik alaptípusa(int, byte, short, long, double, float).

ha x86-ra épít, használja aobjc_msgSend_stret értéket minden olyan értéktípushoz, amely nem felsorolás, vagy a felsorolás bármely alaptípusa(int, byte, short, long, double, float)és amelynek natív mérete nagyobb, mint 8 bájt.

saját aláírások létrehozása

szükség esetén a következő lényeg használható saját aláírások létrehozására.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.