Řešení problému "UIWindow does not contain a definition for Current" v Uno Platform

Uno Platform

4 years ago

Jedním z častých problémů, na které vývojáři naráží při portování UWP aplikací do Uno Platform je následující chyba:

Error CS1061 'UIWindow' does not contain a definition for 'Current' and no accessible extension method 'Current' accepting a first argument of type 'UIWindow' could be found (are you missing a using directive or an assembly reference?)

K této chybě může dojít například pokud provedeme v App.xaml.cs refaktoring na základě doporučení Visual Studio IntelliSense a odstraníme plnou kvalifikaci jmenného prostoru při použití Window.Current. Kupříkladu z:

Na:

Tento refaktoring se zdá býti neškodným, avšak tato "neškodnost" závisí na kontextu, ve kterém pracujeme. Pro UWP, Android a WASM není žádný problém, ale jakmile se přepneme na iOS přes target platform dropdown:

Switching to iOS platform in platform target dropdown

Přepnutí na iOS

Dostaneme zničehonic červené podtržení přímo v kódu:

Red squiggle is here!

Podtržení chyby je zde!

Důvodem je, že Window ve třídě App na iOS neodkazuje na implementaci Windows.UI.Xaml.Window v Uno Platform, ale na vlastnost Window typu UIWindow. A kde se tato vlastnost vzala? Odpověď je v tom, jak je třída Windows.UI.Xaml.Application na iOS v Uno Platform implementována. Když nahlédneme do zdrojového kódu na GitHubu, uvidíme následující deklaraci:

Zde tkví náš problém. iOS UIApplicationDelegate obsahuje vlastnost Window pro manipulaci s oknem aplikace, takže pokud v rámci kterékoliv třídy zděděné od Application odkazuje na Window, vlastnost implicitně dostává přednost před typem Window, dle pravidel jazyka C#. Oprava je jednoduchá - použijme plnou deklaraci jmenného prostoru, tedy Windows.UI.Xaml.Window, kdykoliv chceme pracovat s oknem v UWP/Uno Platform. Na analogický problém můžeme narazit i na ostatních platformách. Například na Androidu jsem jej při portování aplikace našel při práci s událostmi dragging. Třída DragEventArgs na Androidu je deklarována jako vložený typ třídy Android.Views.View, což je vlastně předek všech ovladacích prvků Uno Platform na Androidu:

DragEventArgs on Android

DragEventArgs on Android

Chybu opravíme znovu tak, že plně kvalifikujeme typ jmenným prostorem: Windows.UI.Xaml.DragEventArgs.

Shrnutí

Uno Platform cílí na více platforem, takže vždy pomůže myslet na možnost změny platformy, pro kterou aktuální soubor zdrojového kódu prohlížíme. Jakmile narazíme na chybu, která brání kompilaci, ale v kódu ji nevidíme, přepnutí platformy nám pomůže příčinu problému odhalit.