Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Jazyk Objective-C je založený na selektorech. Selektor je zpráva, která se dá odeslat do objektu nebo třídy. Xamarin.iOS mapuje selektory instancí na metody instancí a selektory tříd na statické metody.
Na rozdíl od normálních funkcí jazyka C (a podobně jako členské funkce jazyka C++) nelze přímo vyvolat selektor pomocí volání nespravovaného volání, selektory se odesílají do Objective-C třídy nebo instance pomocíobjc_msgSend Funkce.
Další informace o zprávách najdete Objective-Cv příručce Práce s objekty společnosti Apple.
Příklad
Předpokládejme, že chcete vyvolat sizeWithFont:forWidth:lineBreakMode: selektor zapnutý NSString.
Deklarace (z dokumentace společnosti Apple) je:
- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode
Toto rozhraní API má následující charakteristiky:
- Návratový typ je
CGSizeurčený pro sjednocené rozhraní API. - Parametr
fontje UIFont (a typ (nepřímo) odvozený z NSObject a je mapován na System.IntPtr. - Parametr
width, aCGFloat, je namapován nanfloat. - Parametr
lineBreakMode, aUILineBreakMode, již byl vázán v Xamarin.iOS jakoUILineBreakModeVýčtu.
Všechny deklarace by se měly shodovat objc_msgSend :
CGSize objc_msgSend(
IntPtr target,
IntPtr selector,
IntPtr font,
nfloat width,
UILineBreakMode mode
);
Deklarujte ji následujícím způsobem:
[DllImport (Constants.ObjectiveCLibrary, EntryPoint="objc_msgSend")]
static extern CGSize cgsize_objc_msgSend_IntPtr_float_int (
IntPtr target,
IntPtr selector,
IntPtr font,
nfloat width,
UILineBreakMode mode
);
Chcete-li volat tuto metodu, použijte kód, například následující:
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
);
Byla-li vrácená hodnota strukturou menší než 8 bajtů (podobně jako starší SizeF použitá před přepnutím na sjednocená rozhraní API), výše uvedený kód by běžel na simulátoru, ale v zařízení došlo k chybovému ukončení. Chcete-li volat selektor, který vrátí hodnotu menší než 8 bitů velikosti, deklarujte objc_msgSend_stret funkci:
[DllImport (MonoTouch.Constants.ObjectiveCLibrary, EntryPoint="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
);
Chcete-li volat tuto metodu, použijte kód, například následující:
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
);
Vyvolání selektoru
Vyvolání selektoru má tři kroky:
- Získejte cíl selektoru.
- Získejte název selektoru.
- Volání
objc_msgSends příslušnými argumenty
Cíle selektoru
Cíl selektoru je buď instance objektu Objective-C , nebo třída. Pokud je cílem instance a pochází z vázaného typu Xamarin.iOS, použijte ObjCRuntime.INativeObject.Handle vlastnost.
Pokud je cílem třída, použijte ObjCRuntime.Class k získání odkazu na instanci třídy a pak použijte Class.Handle vlastnost.
Názvy selektorů
Názvy selektorů jsou uvedené v dokumentaci společnosti Apple. Zahrnuje například NSStringsizeWithFont: a sizeWithFont:forWidth:lineBreakMode: selektory. Vložené a koncové dvojtečky jsou součástí názvu selektoru a nelze je vynechat.
Jakmile budete mít název selektoru, můžete pro něj vytvořit ObjCRuntime.Selector instanci.
Volání objc_msgSend
objc_msgSend odešle zprávu (selektor) objektu. Tato řada funkcí má alespoň dva požadované argumenty: cíl selektoru (instance nebo popisovač třídy), samotný selektor a všechny argumenty požadované pro selektor. Argumenty instance a selektoru musí být System.IntPtra všechny zbývající argumenty musí odpovídat typu, který selektor očekává, například nint pro intSystem.IntPtr nebo pro všechny NSObjectodvozené typy. Použít NSObject.Handle vlastnost k získání IntPtr instance Objective-C typu.
Existuje více než jedna objc_msgSend funkce:
- Slouží
objc_msgSend_stretpro selektory, které vrací strukturu. V ARM to zahrnuje všechny návratové typy, které nejsou výčtem nebo žádným z předdefinovaných typů jazyka C (char, ,shortint,long,float, ).doubleV x86 (simulátoru) musí být tato metoda použita pro všechny struktury větší než 8 bajtů velikosti (CGSizeje 8 bajtů a nepoužíváobjc_msgSend_stretse v simulátoru). - Slouží
objc_msgSend_fpretpouze pro selektory, které vracejí hodnotu s plovoucí desetinou čárkou pouze u x86. Tuto funkci není nutné používat v ARM; místo toho použijteobjc_msgSend. - Hlavní objc_msgSend funkce se používá pro všechny ostatní selektory.
Jakmile se rozhodnete, které objc_msgSend funkce potřebujete volat (simulátor a zařízení můžou vyžadovat jinou metodu), můžete pomocí normální [DllImport] metody deklarovat funkci pro pozdější vyvolání.
Soubor předpřipravených objc_msgSend deklarací lze nalézt v ObjCRuntime.Messagingčásti .
Různé vyvolání na simulátoru a zařízení
Jak je popsáno výše, Objective-C má tři druhy objc_msgSend metod: jeden pro pravidelné vyvolání, jeden pro vyvolání, které vracejí hodnoty s plovoucí desetinou čárkou (pouze x86) a jeden pro vyvolání, které vracejí hodnoty struktury. Druhá zahrnuje příponu _stret v ObjCRuntime.Messaging.
Pokud voláte metodu, která vrátí určité struktury (pravidla popsaná níže), musíte metodu vyvolat s návratovou out hodnotou jako první parametr jako hodnotu:
// The following returns a PointF structure:
PointF ret;
Messaging.PointF_objc_msgSend_stret_PointF_IntPtr (out ret, this.Handle, selConvertPointFromWindow.Handle, point, window.Handle);
Pravidlo, kdy použít metodu _stret_ , se liší v x86 a ARM.
Pokud chcete, aby vazby fungovaly na simulátoru i na zařízení, přidejte kód, například následující:
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);
}
Použití metody objc_msgSend_stret
Při sestavování pro ARM použijte objc_msgSend_stretpro libovolný typ hodnoty, který není výčtem nebo žádným ze základních typů výčtu (int, byte, , longshort, double). float
Při sestavování pro x86 použijte objc_msgSend_stretpro libovolný typ hodnoty, který není výčtem nebo žádným ze základních typů výčtu (int, , , longshort, ) doublefloata jehož nativní velikost je větší než 8 bytebajtů.
Vytváření vlastních podpisů
V případě potřeby můžete k vytvoření vlastních podpisů použít následující gist .