Objective-C-velgere I Xamarin.iOS

  • 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, a CGFloat, er tilordnet til nfloat.
  • parameteren lineBreakMode, a UILineBreakMode, 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:

  1. Hent velgermålet.
  2. Hent navnet på velgeren.
  3. 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

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 ikke objc_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 bruker objc_msgSend.
  • mainobjc_msgSendfunction brukes for alle andre velgere.

når du har bestemt hvilken objc_msgSendfunksjon(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.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.