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 kapotou, pomůže jak interpretovat stávající dokumentaci s objektivem C# a laděním problémů, když se objeví.

V Xamarin.Mac aplikace přemístit dva světy: existuje Objective-C založený modul runtime obsahující instance nativních tříd (NSStringatdNSApplication.) a modul runtime jazyka C# obsahuje instance spravovaných tříd (System.StringHttpClientatd.). Mezi těmito dvěma světy vytvoří Xamarin.Mac 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 (jako jsou metody delegáta aplikace). Obecně platí, že volání Objective-C se zpracovávají transparentně prostřednictvím volání nespravovaných kódů a některé kódy modulu runtime Xamarin poskytuje.

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

Aby Objective-C však bylo možné volat zpět do objektů jazyka C# aplikace, musí být vystaveny způsobem, který Objective-C dokáže porozumět. 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 modul runtime nyní bude vědět o třídě volané MyClass selektory init 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ých volání, které aplikace přijímá, bude buď prostřednictvím přepsání metod u base tříd (například AppDelegate, Delegates, DataSources) nebo akcí předávaných do rozhraní API. Ve všech těchtopřípadechch Export

Runthrough konstruktoru

V mnoha případech bude vývojář muset vystavit rozhraní API Objective-C pro vytváření tříd jazyka C# aplikace modulu runtime, aby bylo možné vytvořit instanci z míst, jako je volání v souborech Storyboard nebo 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)
{
}

Obecně platí, že vývojář by měl ponechat IntPtr konstruktory, NSCoder které se generují při vytváření některých typů, jako jsou vlastní NSViews samotné. 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 se chybově ukončí uvnitř nativního kódu a může být obtížné zjistit přesně tento problém.

Správa paměti a cykly

Správa paměti v Xamarin.Mac je v mnoha ohledech 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řed časem

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

Doba potřebná ke kompilaci mono modulu runtime jiT může zpomalit spuštění aplikace Xamarin.Mac až o 20 %, protože je potřeba vygenerovat potřebný strojový kód.

Z důvodu omezení společnosti Apple pro iOS není kompilace kódu IL JIT k dispozici pro Xamarin.iOS. V důsledku toho jsou všechny aplikace Xamarin.iOS kompilované do strojového kódu během cyklu sestavení 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ý kompiluje většinu potřebného strojového kódu, ale umožňuje modulu runtime kompilovat potřebné trampoliny a flexibilitu nadále podporovat Reflection.Emit (a další případy použití, které aktuálně pracují na Xamarin.Mac).

Existují dvě hlavní oblasti, ve kterých může AOT pomoct aplikaci Xamarin.Mac:

  • Lepší nativní protokoly chybových ukončení – Pokud se aplikace Xamarin.Mac chybově ukončí 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 chybových ukončení s snímky JIT se obtížně analyzují. Vzhledem k tomu, že snímky JIT nemají informace o ladění, bude několik řádků s šestnáctkovým posunem a bez povědomí o tom, co se děje. AOT generuje "skutečné" pojmenované rámce a trasování je mnohem jednodušší číst. To také znamená, že aplikace Xamarin.Mac bude pracovat lépe s nativními nástroji, jako je lldb a Instruments.
  • 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 veškerého kódu trvat značné množství času. AOT to dělá předem.

Povolení kompilace AOT

AOT je v Xamarin.Mac povolen tak, že dvakrát kliknete na název projektu v Průzkumník řešení, přejdete na Build mac a přidáte --aot:[options] do pole Další argumenty mmp: pole (kde [options] je jedna nebo více možností pro řízení typu AOT, viz níže). Příklad:

Přidání AOT do dalších argumentů mmp

Důležité

Povolení kompilace AOT výrazně zvyšuje čas sestavení, někdy až několik minut, ale může zkrátit dobu spuštění aplikace o průměrně 20 %. V důsledku toho by kompilace AOT měla být 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.MacSystem a mscorlib sestavení.
  • sdk – AOT kompiluje Xamarin.Mac sestavení AOT (Base Class Library) (BCL).
  • |hybrid – Přidáním této možnosti do jedné z výše uvedených možností povolíte hybridní technologii 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.

Například --aot:all,-MyAssembly.dll by bylo možné povolit kompilaci AOT pro všechna sestavení v MonoBundle s výjimkou MyAssembly.dll a --aot:core|hybrid,+MyOtherAssembly.dll,-mscorlib.dll umožní hybridní, kód AOT zahrnuje MyOtherAssembly.dll a s výjimkou mscorlib.dll.

Částečná statická registrar

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

Kromě toho a novinka v Xamarin.Mac, částečná statická Registrar (jako průkopnice Xamarin.iOS) může výrazně snížit dobu spuštění aplikace Xamarin.Mac v konfiguraci ladění . Když se dozvíte, 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 statickým a dynamickým a co tato "částečná statická" verze dělá.

O aplikaci registrar

Pod kapucí jakékoli aplikace Xamarin.Mac leží cocoa architektura 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 tohoto úkolu se zpracovává metodou registrar, která se provádí uvnitř NSApplication.Init () metody. To je jeden z důvodů, proč jakékoli použití rozhraní API Cocoa v Xamarin.Mac vyžaduje NSApplication.Init , aby se volala jako první.

Úloha registrarje informovat Objective-C modul runtime o existenci tříd jazyka C# aplikace, které jsou odvozeny od tříd, jako NSApplicationDelegatejsou , NSView, NSWindowa NSObject. To vyžaduje kontrolu všech typů v aplikaci, aby bylo možné určit, co je potřeba registrovat a jaké prvky jednotlivých typů se mají hlásit.

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ář znát následující skutečnosti:

  • Statická registrace může výrazně snížit dobu spuštění, ale může výrazně zpomalit časy sestavení (obvykle více než čas dvojitého ladění sestavení). Toto bude výchozí nastavení pro sestavení konfigurace vydané verze .
  • Dynamická registrace zpožďuje tuto práci, 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é ve výchozím nastavení dynamické registrace a jejichž odraz je pomalejší.

Částečná statická registrace, která byla poprvé zavedena v Xamarin.iOS 8.13, poskytuje vývojářům to nejlepší z obou možností. Díky předběžnému výpočtu informací o registraci všech prvků v Xamarin.Mac.dll Xamarin.Mac a jejich odeslání do statické knihovny (které je potřeba propojit pouze v době sestavení), Společnost Microsoft odebrala většinu času reflexe dynamického registrar prostředí, aniž by to mělo vliv na čas sestavení.

Povolení částečné statické registrar

Částečná statická Registrar je v Xamarin.Mac povolena poklikáním na název projektu 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:

Přidání částečné statické registrar k dalším argumentům mmp

Další materiály

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