Objective-C vælgere.iOS

  • 07/12/2017
  • 4 minutter at læse
    • d
    • d
    • c
    • a

Objective-C-sproget er baseret på vælgere. En vælger er en besked, der kan sendes til et objekt eller en klasse. – Amarin.iOS kortlægger instansvalgtil instansmetoder og klassevælgere til statiske metoder.

i modsætning til normale C-funktioner (og lignende C++ – medlemsfunktioner) kan du ikke direkte påberåbe dig en vælger ved hjælp AFP/Invoke i stedet sendes vælgere til en Objective-C-klasse eller instans ved hjælp af funktionenobjc_msgSend.

for mere information om meddelelser i Objective-C, se på Apples arbejde med Objectsguide.

eksempel

Antag at du vil påberåbesizeWithFont:forWidth:lineBreakMode:vælgeren på NSString.Erklæringen (fra Apples dokumentation) er:

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

denne API har følgende egenskaber:

  • returtypen er CGSize for Unified API.
  • parameteren font er en UIFont (og en type (indirekte) afledt af NSObject og er kortlagt til System.IntPtr.
  • parameteren width, a CGFloat, er kortlagt til nfloat.
  • parameteren lineBreakMode, a UILineBreakMode, er allerede bundet i Ksamarin.iOS som optællingenUILineBreakMode.

at sætte det hele sammen, objc_msgSend erklæringen skal matche:

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 at kalde denne metode skal du bruge 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);

havde den returnerede værdi været en struktur, der var mindre end 8 bytes i størrelse (som den ældre SizeF, der blev brugt, før du skiftede til Unified API ‘ er), ville ovenstående kode have kørt på simulatoren, men styrtede ned på enheden. Hvis du vil kalde en vælger, der returnerer en værdi, der er mindre end 8 bit i størrelse, skal du erklære funktionen 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);

for at kalde denne metode skal du bruge 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åkaldelse af en vælger

påkaldelse af en vælger har tre trin:

  1. få vælgeren mål.
  2. få vælgerens navn.
  3. Ring objc_msgSend med de relevante argumenter.

Vælgermål

et vælgermål er enten en objektinstans eller en Objective-C-klasse. Hvis målet er et eksempel og kom fra en bundet Ksamarin.iOS type, Brug egenskaben ObjCRuntime.INativeObject.Handle.

hvis målet er en klasse, skal du bruge ObjCRuntime.Class for at få en reference til klasseninstance og derefter bruge egenskaben Class.Handle.

Vælgernavne

Vælgernavne er angivet i Apples dokumentation. For eksempel inkluderer NSString sizeWithFont: og sizeWithFont:forWidth:lineBreakMode: vælgere. De indlejrede og efterfølgende kolonner er en del af vælgernavnet og kan ikke udelades.

når du har et vælgernavn, kan du oprette en ObjCRuntime.Selector instans til det.

opkald objc_msgSend

objc_msgSend sender en besked (vælger) til et objekt. Denne familie af funktioner tager mindst to krævede argumenter: vælgermålet (aninstance eller klassehåndtag), selve vælgeren og eventuelle argumenterkræves for vælgeren. Eksempel-og vælgerargumenterne skal væreSystem.IntPtr, og alle resterende argumenter skal svare til typen theselector forventer, for eksempel en nint for en int eller enSystem.IntPtr for alle NSObject-afledte typer. Brug egenskabenNSObject.Handletil at få en IntPtr til en forekomst af Objective-C-typen.

der er mere end en objc_msgSend funktion:

  • brug objc_msgSend_strettil vælgere, der returnerer en struktur. På ARM, dette inkluderer alle returtyper, der ikke er en optælling eller nogen af de C-indbyggede typer (char,short, int, long, float, double). På 86 (simulatoren) skal denne metode bruges til alle strukturer større end 8 byte i størrelse(CGSize er 8 byte og bruger ikke objc_msgSend_stret isimulator).
  • brug objc_msgSend_fprettil vælgere, der kun returnerer en floating point-værdi på 86. Denne funktion behøver ikke bruges på ARM; brug i stedet objc_msgSend.
  • hovedobjc_msgsendfunktionen bruges til alle andre vælgere.

når du har besluttet, hvilken objc_msgSendfunktion(er) du skal ringe til(simulator og enhed kan hver især kræve en anden metode), kan du brugeen normal metode til at erklære funktionen til senere påkaldelse.

et sæt af pre-made objc_msgSenderklæringer kan findes iObjCRuntime.Messaging.

forskellige påkaldelser på simulator og enhed

som beskrevet ovenfor har Objective-C tre slags objc_msgSendmetoder: en til regelmæssige påkaldelser, en til påkaldelser, der returnerer flydende punktværdier (kun 86) og en til påkaldelser, der returnerer værdier. Sidstnævnte omfatter suffikset _stret iObjCRuntime.Messaging.

hvis du påkalder en metode, der returnerer visse strukturer (regler beskrevet nedenfor), skal du påkalde metoden med returværdien som den førsteparameter som en out værdi:

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

reglen for hvornår man skal bruge _stret_ – metoden er forskellig på H86 og ARM.Hvis du vil have dine bindinger til at fungere på både simulatoren og enheden,skal du tilføje 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);}

brug af objc_msgSend_stret-metoden

når du bygger til ARM, skal du brugeobjc_msgSend_strettil enhver værditype, der ikke er en optælling eller nogen af basetyperne til en optælling (int, byte, short, long, double, float).

når du bygger til 86, skal du brugeobjc_msgSend_stretfor enhver værditype, der ikke er en optælling eller nogen af basistyperne til en optælling (int, byte, short, long, double, float)og hvis oprindelige størrelse er større end 8 bytes.

oprettelse af dine egne signaturer

følgende kerne kan bruges til at oprette dine egne signaturer, hvis det kræves.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.