Jak funguje Xamarin.Mac

Ve většině případů se vývojář nebude muset starat o vnitřní "magii" Xamarin.Mac, ale s hrubým pochopením toho, jak věci fungují pod kapucí, vám pomůžou při interpretaci stávající dokumentace s objektivem C# a problémy s laděním při jejich vzniku.

V Xamarin.Mac aplikace přemístit dva světy: je Objective-C založený modul runtime obsahující instance nativních tříd (NSStringatd NSApplication.) a existuje modul runtime jazyka C# obsahující instance spravovaných tříd (System.Stringatd HttpClient.). Mezi těmito dvěma světy Xamarin.Mac vytvoří obousměrný most, aby aplikace mohl volat metody (selektory) v Objective-C (například NSApplication.Init) a Objective-C volat metody jazyka C# aplikace zpět (například metody na delegátovi aplikace). Obecně platí, že volání se Objective-C zpracovávají transparentně prostřednictvím volání P/Invokes a některé kód modulu runtime Xamarin poskytuje.

Zveřejnění tříd nebo metod jazyka C# pro Objective-C

Aby Objective-C se ale mohl vrátit zpět k objektům C# aplikace, musí být vystaveny způsobem, který Objective-C dokáže pochopit. To se provádí prostřednictvím Register atributů a Export atributů. Podívejte se na následující příklad:

[Register ("MyClass")]
public class MyClass : NSObject
{
   [Export ("init")]
   public MyClass ()
   {
   }

   [Export ("run")]
   public void Run ()
   {
   }
}

V tomto příkladu Objective-C bude modul runtime nyní vědět o třídě volané s volanými MyClassinit selektory a run.

Ve většině případů se jedná o podrobnosti implementace, které může vývojář ignorovat, protože většina zpětného volání, kterou aplikace přijímá, bude buď prostřednictvím přepsání metod u base tříd (například AppDelegate, , DelegatesDataSources), nebo akcí předávaných do rozhraní API. Ve všech těchto případech Export nejsou atributy v kódu jazyka C# nezbytné.

Runthrough konstruktoru

V mnoha případech bude vývojář muset vystavit rozhraní API pro vytváření tříd jazyka C# aplikace do Objective-C modulu runtime, aby bylo možné vytvořit instanci z míst, jako je volání v storyboardu nebo souborech XIB. Tady je pět nejběžnějších konstruktorů používaných v aplikacích Xamarin.Mac:

// Called when created from unmanaged code
public CustomView (IntPtr handle) : base (handle)
{
   Initialize ();
}

// Called when created directly from a XIB file
[Export ("initWithCoder:")]
public CustomView (NSCoder coder) : base (coder)
{
   Initialize ();
}

// Called from C# to instance NSView with a Frame (initWithFrame)
public CustomView (CGRect frame) : base (frame)
{
}

// Called from C# to instance NSView without setting the frame (init)
public CustomView () : base ()
{
}

// This is a special case constructor that you call on a derived class when the derived called has an [Export] constructor.
// For example, if you call init on NSString then you don’t want to call init on NSObject.
public CustomView () : base (NSObjectFlag.Empty)
{
}

Vývojář by měl obecně opustit IntPtr a NSCoder konstruktory, které se vygenerují při vytváření některých typů, jako je například vlastní NSViews . Pokud Xamarin.Mac potřebuje volat jeden z těchto konstruktorů v reakci na Objective-C požadavek modulu runtime a odebrali jste ho, aplikace dojde k chybovému ukončení v nativním kódu a může být obtížné přesně zjistit problém.

Správa paměti a cykly

Správa paměti v Xamarin.Mac je mnoha způsoby velmi podobná Xamarin.iOS. Jedná se také o komplexní téma, které je nad rámec tohoto dokumentu. Přečtěte si osvědčené postupy pro paměť a výkon.

Kompilace předem

Aplikace .NET se obvykle při vytváření nekompilují do strojového kódu, místo toho se kompilují do přechodné vrstvy s názvem IL kód, který se při spuštění aplikace zkompiluje do strojového kódu.

Doba potřebná k kompilaci mono runtime do JIT může zpomalit spuštění aplikace Xamarin.Mac až o 20 %, protože to trvá, než se vygeneruje potřebný strojový kód.

Z důvodu omezení uložených společností Apple pro iOS není kompilace kódu IL pro Xamarin.iOS k dispozici. Výsledkem je, že všechny aplikace Xamarin.iOS jsou během cyklu sestavení kompilované do strojového kódu předem ( AOT ).

Novinkou v Xamarin.Mac je schopnost AOT kódu IL během cyklu sestavení aplikace, stejně jako Xamarin.iOS. Xamarin.Mac používá hybridní přístup AOT , který zkompiluje většinu potřebného strojového kódu, ale umožňuje modulu runtime kompilovat potřebné trampoliny a flexibilitu pro pokračování v podpoře Reflex.Emit (a dalších případů použití, které aktuálně pracují na Xamarin.Mac).

Existují dvě hlavní oblasti, kde může AOT pomoci aplikaci Xamarin.Mac:

  • Lepší "nativní" protokoly chyb – Pokud aplikace Xamarin.Mac dojde k chybovému ukončení v nativním kódu, což je běžný výskyt při provádění neplatných volání do rozhraní Cocoa API (například odeslání null do metody, která ji nepřijímá), nativní protokoly chyb s snímky JIT jsou obtížné analyzovat. Vzhledem k tomu, že snímky JIT nemají informace o ladění, budou existovat více řádků s šestnáctkovým posunem a bez povědomí o tom, co se děje. AOT generuje "skutečné" pojmenované snímky a trasování je mnohem jednodušší číst. To také znamená, že aplikace Xamarin.Mac bude lépe pracovat s nativními nástroji, jako jsou lldb a Nástroje.
  • Lepší výkon při spuštění – u velkých aplikací Xamarin.Mac s několika sekundami spuštění může kompilace JIT celý kód trvat značné množství času. AOT to funguje předem.

Povolení kompilace AOT

Funkce AOT je v Xamarin.Mac povolena poklikáním na název Project v Průzkumník řešení, přechodem na build Mac a přidáním --aot:[options] do pole Další argumenty mmp( kde [options] je jedna nebo více možností řízení typu AOT, viz níže). Příklad:

Adding AOT to additional mmp arguments

Důležité

Povolení kompilace AOT výrazně zvyšuje dobu sestavení, někdy až několik minut, ale může zlepšit dobu spuštění aplikace průměrem 20 %. V důsledku toho by měla být kompilace AOT povolena pouze v buildech vydaných verzí aplikace Xamarin.Mac.

Možnosti kompilace Aot

Při povolování kompilace AOT v aplikaci Xamarin.Mac je možné upravit několik různých možností:

  • none - Žádná kompilace AOT. Toto je výchozí nastavení.
  • all - AOT zkompiluje každé sestavení v MonoBundle.
  • core- AOT zkompiluje Xamarin.Maca mscorlibSystem sestavení.
  • sdk - AOT kompiluje Xamarin.Mac sestavení BCL (Base Class Library).
  • |hybrid - Přidání této možnosti do jedné z výše uvedených možností umožňuje hybridní AOT, která umožňuje prokládání IL, ale bude mít za následek delší dobu kompilace.
  • + – Obsahuje jeden soubor pro kompilaci AOT.
  • - – Odebere jeden soubor z kompilace AOT.

--aot:all,-MyAssembly.dll Například by povolovala kompilaci AOT na všech sestaveních v MonoBundle s výjimkouMyAssembly.dll a --aot:core|hybrid,+MyOtherAssembly.dll,-mscorlib.dll povolovala by hybridní kód AOT včetně MyOtherAssembly.dll a vyloučení mscorlib.dll.

Částečná statická registrar

Při vývoji aplikace Xamarin.Mac může být pro splnění termínů vývoje důležité minimalizovat dobu mezi dokončením změny a testováním. Strategie, jako je modularizace základů kódu a testů jednotek, můžou pomoct snížit dobu kompilace, protože snižují dobu, po kterou aplikace bude vyžadovat nákladné úplné opětovné sestavení.

Kromě toho a nové pro Xamarin.Mac, Částečná statická Registrar (jako průkopnický Xamarin.iOS) může výrazně snížit dobu spuštění aplikace Xamarin.Mac v konfiguraci ladění . Pochopení toho, jak použití částečné statické Registrar můžou vymáčknout téměř 5x vylepšení při spuštění ladění, bude mít trochu pozadí o tom, co registrar je, jaký je rozdíl mezi statickou a dynamickou a jakou "částečnou statickou" verzí dělá.

Informace o registrar

Pod kapucí jakékoli aplikace Xamarin.Mac leží architektura Cocoa od Společnosti Apple a Objective-C modulu runtime. Vytvoření mostu mezi tímto "nativním světem" a "spravovaným světem" jazyka C# je primární odpovědností Xamarin.Mac. Část této úlohy je zpracována metodou registrar, která se provádí uvnitř NSApplication.Init () metody. To je jeden z důvodů, proč je nutné volat první použití rozhraní COCOA API v Xamarin.Mac NSApplication.Init .

Úloha registrarje informovat Objective-C modul runtime existence tříd jazyka C#aplikace, které pocházejí z tříd, jako NSApplicationDelegatejsou , , NSViewNSWindowa NSObject. To vyžaduje kontrolu všech typů v aplikaci, aby bylo možné určit, co je potřeba zaregistrovat a jaké prvky jednotlivých typů pro sestavu.

Tuto kontrolu je možné provést dynamicky při spuštění aplikace s reflexí nebo staticky jako krok času sestavení. Při výběru typu registrace by měl vývojář vědět o těchto případech:

  • Statická registrace může výrazně snížit dobu spuštění, ale může výrazně zpomalit časy sestavení (obvykle více než dvakrát ladit čas sestavení). Toto bude výchozí nastavení pro sestavení konfigurace vydaných verzí .
  • Dynamická registrace tuto práci zpožďuje, dokud aplikace nespustí a přeskočí generování kódu, ale tato další práce může při spuštění aplikace vytvořit znatelnou pozastavení (alespoň dvě sekundy). To je obzvláště patrné v sestaveních konfigurace ladění, které se ve výchozím nastavení nastaví na dynamickou registraci a jejichž odraz je pomalejší.

Částečná statická registrace, která byla poprvé představena v Xamarin.iOS 8.13, poskytuje vývojářům nejlepší možnosti obou možností. Předpočítejte si registrační informace o všech elementech v Xamarin.Mac.dll Xamarin.Mac ve statické knihovně (které je potřeba propojit jenom v době sestavení), Společnost Microsoft odebrala většinu času odrazu dynamického registrar času, aniž by to mělo vliv na čas sestavení.

Povolení částečné statické registrar

Částečná statická Registrar funkce je povolená v Xamarin.Mac poklikáním na název Project v Průzkumník řešení, přechodem na build Mac a přidáním --registrar:static do pole Další argumenty mmp: Příklad:

Adding the partial static registrar to additional mmp arguments

Další materiály

Tady je několik podrobnějších vysvětlení toho, jak věci fungují interně: