Práce s nativními typy v multiplatformních aplikacích

Tento článek popisuje použití nových nativních typů rozhraní API pro iOS (nint, nuint, nfloat) v multiplatformní aplikaci, kde se kód sdílí se zařízeními bez iOSu, jako je Android nebo Windows Telefon operačních systémů.

Nativní typy 64 typů fungují s rozhraními API pro iOS a Mac. Pokud píšete také sdílený kód, který běží na Androidu nebo Windows, budete muset spravovat převod sjednocených typů na běžné typy .NET, které můžete sdílet.

Tento dokument popisuje různé způsoby spolupráce s jednotným rozhraním API ze sdíleného nebo společného kódu.

Kdy použít nativní typy

Sjednocená rozhraní API Xamarin.iOS a Xamarin.Mac stále zahrnují intdatové uint typy a float typy SizeFRectangleFa typy.PointF Tyto existující datové typy by se měly dál používat v jakémkoli sdíleném kódu pro různé platformy. Nové nativní datové typy by se měly používat pouze při volání rozhraní API pro Mac nebo iOS, kde je vyžadována podpora typů pracujících s architekturou.

V závislosti na povaze sdíleného kódu může docházet k tomu, že kód napříč platformami může potřebovat řešit nintnuint datové typy a nfloat datové typy. Například: Knihovna, která zpracovává transformace na obdélníkových datech, která byla dříve používá System.Drawing.RectangleF ke sdílení funkcí mezi verzemi Xamarin.iOS a Xamarin.Android aplikace, by bylo potřeba aktualizovat, aby zpracovávala nativní typy v iOSu.

Způsob zpracování těchto změn závisí na velikosti a složitosti aplikace a způsobu sdílení kódu, který byl použit, jak je vidět v následujících částech.

Aspekty sdílení kódu

Jak je uvedeno v dokumentu Možnosti kódu sdílení, existují dva hlavní způsoby sdílení kódu mezi projekty mezi platformami: sdílené projekty a přenosné knihovny tříd. Který z těchto dvou typů byl použit, omezí možnosti, které máme při zpracování nativních datových typů v kódu pro různé platformy.

Projekty knihovny přenosných tříd

Knihovna PCL (Portable Class Library) umožňuje cílit na platformy, které chcete podporovat, a používat rozhraní k poskytování funkcí specifických pro platformu.

Vzhledem k tomu, že typ projektu PCL je zkompilován na a .DLL nemá žádný smysl pro sjednocené rozhraní API, budete nuceni dál používat existující datové typy (int, , uintfloat) ve zdrojovém kódu PCL a typ přetypovat volání tříd a metod PCL ve front-endových aplikacích. Příklad:

using NativePCL;
...

CGRect rect = new CGRect (0, 0, 200, 200);
Console.WriteLine ("Rectangle Area: {0}", Transformations.CalculateArea ((RectangleF)rect));

Sdílené projekty

Typ projektu sdíleného prostředku umožňuje uspořádat zdrojový kód do samostatného projektu, který se pak zahrne a zkompiluje do jednotlivých front-endových aplikací specifických pro konkrétní platformu, a podle potřeby ke správě požadavků specifických pro danou platformu použijte #if direktivy kompilátoru.

Při výběru metody podpory nativních datových typů v projektu sdílených prostředků napříč platformami je potřeba vzít v úvahu velikost a složitost sdílených mobilních aplikací front-endu, které využívají sdílený kód.

Na základě těchto faktorů se můžou implementovat následující typy řešení pomocí direktiv kompilátoru if __UNIFIED__ ... #endif pro zpracování změn specifických pro sjednocené rozhraní API v kódu.

Použití duplicitních metod

Podívejte se na příklad knihovny, která provádí transformace u obdélníkových dat uvedených výše. Pokud knihovna obsahuje pouze jednu nebo dvě velmi jednoduché metody, můžete se rozhodnout vytvořit duplicitní verze těchto metod pro Xamarin.iOS a Xamarin.Android. Příklad:

using System;
using System.Drawing;

#if __UNIFIED__
using CoreGraphics;
#endif

namespace NativeShared
{
    public class Transformations
    {
        #region Constructors
        public Transformations ()
        {
        }
        #endregion

        #region Public Methods
        #if __UNIFIED__
            public static nfloat CalculateArea(CGRect rect) {

                // Calculate area...
                return (rect.Width * rect.Height);

            }
        #else
            public static float CalculateArea(RectangleF rect) {

                // Calculate area...
                return (rect.Width * rect.Height);

            }
        #endif
        #endregion
    }
}

V předchozím kódu, protože rutina CalculateArea je velmi jednoduchá, jsme použili podmíněnou kompilaci a vytvořili samostatnou sjednocenou verzi rozhraní API metody. Na druhou stranu, pokud knihovna obsahovala mnoho rutin nebo několik složitých rutin, toto řešení by nebylo možné, protože by se v něm vyskytoval problém, který by způsoboval synchronizaci všech metod pro úpravy nebo opravy chyb.

Použití přetížení metody

V takovém případě může být řešením vytvořit přetíženou verzi metod pomocí 32bitových datových typů, aby teď jako parametr nebo návratovou hodnotu převeďte CGRect tuto hodnotu na hodnotu (s vědomím RectangleF , že převodem z nfloat na float je ztrátový převod) a voláním původní verze rutiny provedete skutečnou práci. Příklad:

using System;
using System.Drawing;

#if __UNIFIED__
using CoreGraphics;
#endif

namespace NativeShared
{
    public class Transformations
    {
        #region Constructors
        public Transformations ()
        {
        }
        #endregion

        #region Public Methods
        #if __UNIFIED__
            public static nfloat CalculateArea(CGRect rect) {

                // Call original routine to calculate area
                return (nfloat)CalculateArea((RectangleF)rect);

            }
        #endif

        public static float CalculateArea(RectangleF rect) {

            // Calculate area...
            return (rect.Width * rect.Height);

        }

        #endregion
    }
}

Toto je opět vhodné řešení, pokud ztráta přesnosti nemá vliv na výsledky konkrétních potřeb vaší aplikace.

Použití direktiv aliasů

V oblastech, kde je ztráta přesnosti problémem, je dalším možným řešením použití using direktiv k vytvoření aliasu pro datové typy Native a CoreGraphics zahrnutím následujícího kódu na začátek souboru sdíleného zdrojového kódu a převodem potřebných uintinthodnot nebo float hodnot na nint, nuint nebo nfloat:

#if __UNIFIED__
    // Mappings Unified CoreGraphic classes to MonoTouch classes
    using RectangleF = global::CoreGraphics.CGRect;
    using SizeF = global::CoreGraphics.CGSize;
    using PointF = global::CoreGraphics.CGPoint;
#else
    // Mappings Unified types to MonoTouch types
    using nfloat = global::System.Single;
    using nint = global::System.Int32;
    using nuint = global::System.UInt32;
#endif

Takže náš ukázkový kód se pak stane:

using System;
using System.Drawing;

#if __UNIFIED__
    // Map Unified CoreGraphic classes to MonoTouch classes
    using RectangleF = global::CoreGraphics.CGRect;
    using SizeF = global::CoreGraphics.CGSize;
    using PointF = global::CoreGraphics.CGPoint;
#else
    // Map Unified types to MonoTouch types
    using nfloat = global::System.Single;
    using nint = global::System.Int32;
    using nuint = global::System.UInt32;
#endif

namespace NativeShared
{

    public class Transformations
    {
        #region Constructors
        public Transformations ()
        {
        }
        #endregion

        #region Public Methods
        public static nfloat CalculateArea(RectangleF rect) {

            // Calculate area...
            return (rect.Width * rect.Height);

        }
        #endregion
    }
}

Všimněte si, že zde jsme změnili metodu CalculateArea tak, aby vrátila místo nfloat standardu float. To bylo provedeno tak, aby se chyba kompilace nepokusila implicitně převést nfloat výsledek výpočtu (protože obě hodnoty jsou násobené typu nfloat) na návratovou float hodnotu.

Pokud se kód zkompiluje a spustí na zařízení s jiným rozhraním než Sjednocené rozhraní API, mapuje nfloat se na ten, using nfloat = global::System.Single; který implicitně převede na Singlefloat povolení, aby spotřebovaná front-endová aplikace volala metodu CalculateArea beze změny.

Použití převodů typů v front-endové aplikaci

V případě, že vaše front-endové aplikace pouze volat do sdílené knihovny kódu, může být dalším řešením ponechat knihovnu beze změny a zadat přetypování v aplikaci Xamarin.iOS nebo Xamarin.Mac při volání existující rutiny. Příklad:

using NativeShared;
...

CGRect rect = new CGRect (0, 0, 200, 200);
Console.WriteLine ("Rectangle Area: {0}", Transformations.CalculateArea ((RectangleF)rect));

Pokud spotřeba aplikace provádí stovky volání do knihovny sdíleného kódu, nemusí být toto znovu dobrým řešením.

Na základě architektury naší aplikace můžeme nakonec použít jedno nebo více výše uvedených řešení pro podporu nativních datových typů (pokud je to potřeba) v kódu pro různé platformy.

Aplikace Xamarin.Forms

K použití Xamarin.Forms pro víceplatformní uživatelská rozhraní, která se budou také sdílet s aplikací Sjednoceného rozhraní API, je potřeba následující:

  • Celé řešení musí používat verzi 1.3.1 (nebo vyšší) balíčku NuGet Xamarin.Forms.
  • Pro jakékoli vlastní vykreslování Xamarin.iOS použijte stejné typy řešení uvedených výše na základě způsobu sdílení kódu uživatelského rozhraní (sdílený projekt nebo PCL).

Stejně jako u standardní multiplatformní aplikace by se stávající 32bitové datové typy měly používat ve všech sdílených kódech napříč platformami pro většinu situací. Nové nativní datové typy by se měly používat jenom při volání rozhraní API pro Mac nebo iOS, kde je vyžadována podpora typů pracujících s architekturou.

Další podrobnosti najdete v naší dokumentaci k aktualizaci existujících aplikací Xamarin.Forms.

Shrnutí

V tomto článku jsme viděli, kdy používat nativní datové typy v aplikaci sjednoceného rozhraní API a jejich důsledky pro různé platformy. Představili jsme několik řešení, která je možné použít v situacích, kdy se nové nativní datové typy musí používat v knihovnách pro různé platformy. Také jsme viděli rychlý průvodce podporou sjednocených rozhraní API v multiplatformních aplikacích Xamarin.Forms.