Architektura aplikací pro iOS
Aplikace Xamarin.iOS běží v prostředí mono spouštění a k kompilaci kódu C# do jazyka sestavení ARM používají úplnou kompilaci AOT (Head of Time). Spustí se souběžně s modulem Objective-C Runtime. Obě prostředí modulu runtime běží nad jádrem systém UNIX, konkrétně XNU, a zveřejňují různá rozhraní API pro uživatelský kód, což vývojářům umožňuje přístup k podkladovému nativnímu nebo spravovanému systému.
Následující diagram znázorňuje základní přehled této architektury:
Nativní a spravovaný kód: Vysvětlení
Při vývoji pro Xamarin se často používají termíny nativní a spravovaný kód. Spravovaný kód je kód , který má spuštění spravované modulem .NET Framework Common Language Runtime nebo v případě Xamarinu: Mono Runtime. Tomu říkáme zprostředkující jazyk.
Nativní kód je kód, který se bude nativně spouštět na konkrétní platformě (například Objective-C nebo dokonce zkompilovaný kód AOT na čipu ARM). V této příručce se dozvíte, jak AOT zkompiluje spravovaný kód do nativního kódu, a vysvětluje, jak aplikace Xamarin.iOS funguje a plně využívá rozhraní API apple pro iOS prostřednictvím vazeb a zároveň má přístup k . Net je seznam BCL a sofistikovaný jazyk, jako je C#.
AOT
Když zkompilujete libovolnou aplikaci platformy Xamarin, spustí se kompilátor Mono C# (nebo F#) a zkompiluje kód jazyka C# a F# do jazyka MSIL (Microsoft Intermediate Language). Pokud používáte Xamarin.Android, aplikaci Xamarin.Mac nebo dokonce aplikaci Xamarin.iOS v simulátoru, modul CLR (Common Language Runtime) .NET zkompiluje jazyk MSIL pomocí kompilátoru JIT (Just in Time). Za běhu se zkompiluje do nativního kódu, který může běžet ve správné architektuře pro vaši aplikaci.
Existuje však omezení zabezpečení pro iOS nastavené společností Apple, které zakáže spuštění dynamicky generovaného kódu na zařízení. K zajištění dodržování těchto bezpečnostních protokolů používá Xamarin.iOS místo toho kompilátor AOT (Head of Time) ke kompilaci spravovaného kódu. Tím se vytvoří nativní binární soubor pro iOS, který je volitelně optimalizovaný s LLVM pro zařízení, která je možné nasadit na procesor založený na ARM společnosti Apple. Hrubý diagram toho, jak to zapadá, je znázorněno níže:
Použití AOT má řadu omezení, která jsou podrobně popsána v průvodci omezeními . Poskytuje také řadu vylepšení jit prostřednictvím snížení doby spuštění a různých optimalizací výkonu.
Teď, když jsme prozkoumali, jak je kód zkompilován ze zdroje do nativního kódu, pojďme se podívat, jak nám Xamarin.iOS umožňuje psát plně nativní aplikace pro iOS.
Voliče
S Xamarinem máme dva samostatné ekosystémy, .NET a Apple, které musíme spojit dohromady, aby se zdálo co nejfektivněnější, abychom zajistili, že konečným cílem je bezproblémové uživatelské prostředí. V části výše jsme viděli, jak dva moduly runtime komunikují, a možná jste velmi dobře slyšeli o termínu "vazby", což umožňuje použití nativních rozhraní API pro iOS v Xamarinu. Vazby jsou podrobně vysvětleny v naší Objective-C dokumentaci k vazbám , takže prozatím se podíváme, jak funguje iOS pod kapotou.
Nejprve musí existovat způsob, jak zpřístupnit Objective-C jazyku C#, který se provádí prostřednictvím selektorů. Selektor je zpráva, která je odeslána do objektu nebo třídy. Díky Objective-C tomu se provádí prostřednictvím funkcí objc_msgSend . Další informace o používání selektorů najdete v průvodci Objective-C selektory . Také musí existovat způsob, jak zpřístupnit spravovaný kód Objective-C, což je složitější vzhledem k tomu, že Objective-C neví nic o spravovaném kódu. Abychom to mohli obejít, používáme Registrars. Tyto informace jsou podrobněji vysvětleny v další části.
Registrars
Jak je uvedeno výše, jedná se o registrar kód, který zveřejňuje spravovaný kód Objective-C. Provede to vytvořením seznamu každé spravované třídy, která je odvozena z NSObject:
Pro všechny třídy, které nezalamují existující Objective-C třídu, vytvoří novou Objective-C třídu se zrcadlícími všemi spravovanými Objective-C členy, kteří mají atribut [
Export
].V implementacích každého člena Objective–C se kód přidá automaticky pro volání zrcadlového spravovaného člena.
Níže uvedený pseudokód ukazuje příklad toho, jak se to dělá:
C# (spravovaný kód)
class MyViewController : UIViewController{
[Export ("myFunc")]
public void MyFunc ()
{
}
}
Objective-C:
@interface MyViewController : UIViewController { }
-(void)myFunc;
@end
@implementation MyViewController {}
-(void) myFunc
{
/* code to call the managed MyViewController.MyFunc method */
}
@end
Spravovaný kód může obsahovat atributy a [Export]
, že používá vědět, [Register]
že registrar objekt musí být vystaven Objective-C.
Atribut [Register]
se používá k určení názvu vygenerované Objective-C třídy v případě, že výchozí vygenerovaný název není vhodný. Všechny třídy odvozené z NSObject jsou automaticky registrovány v Objective-C.
Požadovaný [Export]
atribut obsahuje řetězec, což je selektor použitý ve vygenerované Objective-C třídě.
V Xamarin.iOS existují dva typy registrars použití – dynamické a statické:
Dynamická – dynamická registrars registrar provede registraci všech typů v sestavení za běhu. Dělá to pomocí funkcí poskytovaných rozhraním Objective-CAPI modulu runtime. Dynamická funkce registrar má proto pomalejší spouštění, ale rychlejší čas sestavení. Toto je výchozí nastavení pro simulátor iOS. Nativní funkce (obvykle v jazyce C), označované jako trampoliny, se používají jako implementace metod při použití dynamické registrars. Liší se mezi různými architekturami.
Static registrars – Statický registrar generuje Objective-C kód během sestavení, který se pak zkompiluje do statické knihovny a propojil do spustitelného souboru. To umožňuje rychlejší spuštění, ale během sestavování trvá déle. Používá se ve výchozím nastavení pro sestavení zařízení. Statickou funkci registrar lze také použít se simulátorem iOS předáním
--registrar:static
atributumtouch
v možnostech sestavení projektu, jak je znázorněno níže:
Další informace o specifikách systému pro registraci typů iOS, který používá Xamarin.iOS, najdete v průvodci typem Registrar .
Spuštění aplikace
Vstupní bod všech spustitelných souborů Xamarin.iOS je poskytován funkcí s názvem xamarin_main
, která inicializuje mono.
V závislosti na typu projektu se provede následující:
- U běžných aplikací pro iOS a tvOS se volá spravovaná metoda Main poskytovaná aplikací Xamarin. Tato spravovaná metoda Main pak volá
UIApplication.Main
, což je vstupní bod pro Objective-C. UIApplication.Main je vazba metody Objective-CUIApplicationMain
. - Pro rozšíření se volá nativní funkce (
NSExtensionMain
nebo (NSExtensionmain
pro rozšíření WatchOS) poskytovaná knihovnami Apple. Vzhledem k tomu, že tyto projekty jsou knihovny tříd a ne spustitelné projekty, neexistují žádné spravované metody Main ke spuštění.
Veškerá tato sekvence spuštění se zkompiluje do statické knihovny, která se pak propojila s posledním spustitelným souborem, takže vaše aplikace ví, jak se dostat ze země.
V tuto chvíli se naše aplikace spustila, Mono běží, jsme ve spravovaném kódu a víme, jak volat nativní kód a jak se volat zpět. Další věcí, kterou musíme udělat, je skutečně začít přidávat ovládací prvky a vytvářet aplikaci interaktivně.
Generátor
Xamarin.iOS obsahuje definice pro každé jedno rozhraní API pro iOS. Můžete procházet kteroukoli z těchto možností v úložišti MaciOS na GitHubu. Tyto definice obsahují rozhraní s atributy a také všechny nezbytné metody a vlastnosti. Například následující kód slouží k definování UIToolbar v oboru názvů UIKit. Všimněte si, že se jedná o rozhraní s řadou metod a vlastností:
[BaseType (typeof (UIView))]
public interface UIToolbar : UIBarPositioning {
[Export ("initWithFrame:")]
IntPtr Constructor (CGRect frame);
[Export ("barStyle")]
UIBarStyle BarStyle { get; set; }
[Export ("items", ArgumentSemantic.Copy)][NullAllowed]
UIBarButtonItem [] Items { get; set; }
[Export ("translucent", ArgumentSemantic.Assign)]
bool Translucent { [Bind ("isTranslucent")] get; set; }
// done manually so we can keep this "in sync" with 'Items' property
//[Export ("setItems:animated:")][PostGet ("Items")]
//void SetItems (UIBarButtonItem [] items, bool animated);
[Since (5,0)]
[Export ("setBackgroundImage:forToolbarPosition:barMetrics:")]
[Appearance]
void SetBackgroundImage ([NullAllowed] UIImage backgroundImage, UIToolbarPosition position, UIBarMetrics barMetrics);
[Since (5,0)]
[Export ("backgroundImageForToolbarPosition:barMetrics:")]
[Appearance]
UIImage GetBackgroundImage (UIToolbarPosition position, UIBarMetrics barMetrics);
...
}
Generátor, volaný btouch
v Xamarin.iOS, přebírá tyto definiční soubory a používá nástroje .NET ke kompilaci do dočasného sestavení. Toto dočasné sestavení však nelze použít k volání Objective-C kódu. Generátor pak přečte dočasné sestavení a vygeneruje kód jazyka C#, který lze použít za běhu.
To je důvod, proč například když do souboru .cs definice přidáte náhodný atribut, nezobrazí se ve výstupním kódu. Generátor o něm neví, a proto btouch
ho neví hledat v dočasném sestavení, aby ho vystavil.
Jakmile se Xamarin.iOS.dll vytvoří, mtouch seskupí všechny komponenty dohromady.
Na vysoké úrovni toho dosahuje provedením následujících úloh:
- Vytvořte strukturu sady aplikací.
- Zkopírujte ve spravovaných sestaveních.
- Pokud je propojení povolené, spusťte spravovaný linker pro optimalizaci sestavení tak, že vytrháte nepoužívané části.
- Kompilace AOT.
- Vytvořte nativní spustitelný soubor, který vypíše řadu statických knihoven (jednu pro každé sestavení), které jsou propojeny s nativním spustitelným souborem, aby se nativní spustitelný soubor skládá z spouštěcího kódu, registrar kódu (pokud je statické) a všech výstupů kompilátoru AOT.
Podrobnější informace o linkeru a jeho použití najdete v průvodci linkerem.
Shrnutí
Tato příručka se podívala na kompilaci aplikací Xamarin.iOS a prozkoumala Xamarin.iOS a její vztah k Objective-C podrobnostem.