Přehled sjednoceného rozhraní API
Jednotné rozhraní API Xamarinu umožňuje sdílet kód mezi Macem a iOSem a podporovat 32 a 64bitové aplikace se stejným binárním souborem. Jednotné rozhraní API se ve výchozím nastavení používá v nových projektech Xamarin.iOS a Xamarin.Mac.
Důležité
Rozhraní API Xamarin Classic, které předchází sjednocenému rozhraní API, je zastaralé.
- Poslední verze Xamarin.iOS, která podporuje klasické rozhraní API (monotouch.dll), byla Xamarin.iOS 9.10.
- Xamarin.Mac stále podporuje klasické rozhraní API, ale už se neaktualizuje. Vzhledem k tomu, že je zastaralý, vývojáři by měli přesunout své aplikace do sjednoceného rozhraní API.
Aktualizace klasických aplikací založených na rozhraní API
Postupujte podle příslušných pokynů pro vaši platformu:
- Aktualizace existujících aplikací
- Aktualizace existujících aplikací pro iOS
- Aktualizace existujících aplikací pro Mac
- Aktualizace existujících aplikací Xamarin.Forms
- Migrace vazby na Unified API
Tipy pro aktualizaci kódu na Unified API
Bez ohledu na to, které aplikace migrujete, si projděte tyto tipy , které vám pomůžou úspěšně aktualizovat sjednocené rozhraní API.
Rozdělení knihovny
Od tohoto okamžiku se naše rozhraní API zobrazí dvěma způsoby:
- Klasické rozhraní API: Omezeno na 32 bitů (pouze) a vystavené v
monotouch.dll
sestaveních.XamMac.dll
- Sjednocené rozhraní API: Podpora 32bitového i 64bitového vývoje s jedním rozhraním API dostupným v sestaveních
Xamarin.iOS.dll
aXamarin.Mac.dll
sestaveních.
To znamená, že pro podnikové vývojáře (necílující App Store) můžete dál používat stávající klasická rozhraní API, protože je budeme udržovat navždy nebo můžete upgradovat na nová rozhraní API.
Změny oboru názvů
Abychom snížili třecí plochy pro sdílení kódu mezi produkty Mac a iOS, měníme obory názvů pro rozhraní API v produktech.
Z našeho produktu pro iOS a MonoMac z našeho produktu Mac v datových typech zahodíme předponu MonoTouch.
Díky tomu je jednodušší sdílet kód mezi platformami Mac a iOS, aniž byste se museli chystnout k podmíněné kompilaci a snížit šum v horní části souborů zdrojového kódu.
- Klasické rozhraní API: Obory názvů používají
MonoTouch.
neboMonoMac.
předponu. - Jednotné rozhraní API: Žádná předpona oboru názvů
Výchozí hodnoty modulu runtime
Jednotné rozhraní API ve výchozím nastavení používá systém uvolňování paměti SGen a nový systém pro počítání odkazů pro sledování vlastnictví objektu. Tato stejná funkce se převela na Xamarin.Mac.
To řeší řadu problémů, se kterými se vývojáři setkávají se starým systémem a také usnadňují správu paměti.
Všimněte si, že nové refcount je možné povolit i pro klasické rozhraní API, ale výchozí nastavení je konzervativnější a nevyžaduje, aby uživatelé udělali žádné změny. S jednotným rozhraním API jsme využili příležitost změnit výchozí nastavení a poskytnout vývojářům všechna vylepšení ve stejnou dobu, kdy refaktorují a znovu testují svůj kód.
Změny rozhraní API
Sjednocené rozhraní API odebere zastaralé metody a v klasických rozhraních API došlo k překlepům v názvech rozhraní API, když byly svázány s původními obory názvů MonoTouch a MonoMac v klasických rozhraních API. Tyto instance byly opraveny v nových sjednocených rozhraních API a bude nutné je aktualizovat ve vašich komponentách, v aplikacích pro iOS a Mac. Tady je seznam nejběžnějších, na které můžete narazit:
Název klasické metody rozhraní API | Název metody sjednoceného rozhraní API |
---|---|
UINavigationController.PushViewControllerAnimated() |
UINavigationController.PushViewController() |
UINavigationController.PopViewControllerAnimated() |
UINavigationController.PopViewController() |
CGContext.SetRGBFillColor() |
CGContext.SetFillColor() |
NetworkReachability.SetCallback() |
NetworkReachability.SetNotification() |
CGContext.SetShadowWithColor |
CGContext.SetShadow |
UIView.StringSize |
UIKit.UIStringDrawing.StringSize |
Úplný seznam změn při přechodu z klasického rozhraní API na sjednocené rozhraní API najdete v dokumentaci k rozdílům v rozhraní API classic (monotouch.dll) v porovnání s rozdíly v rozhraní API unified (Xamarin.iOS.dll).
Aktualizace na sjednocenou
V rámci sjednoceného rozhraní API není k dispozici několik starých nebo poškozených nebo zastaralých rozhraní API v klasickémprostředí. Před spuštěním (ručního nebo automatizovaného) upgradu může být jednodušší opravit CS0616
upozornění, protože se [Obsolete]
zobrazí zpráva atributu (část upozornění), která vás provede správným rozhraním API.
Všimněte si, že publikujeme rozdíl klasických a sjednocených změn rozhraní API, které je možné použít před nebo po aktualizacích projektu. Zastaralá volání v modelu Classic budou stále opravovat časová úspora (méně vyhledávání dokumentace).
Podle těchto pokynů aktualizujte stávající aplikace pro iOS nebo Mac na sjednocené rozhraní API. Projděte si zbývající část této stránky a tyto tipy pro další informace o migraci kódu.
NuGet
Balíčky NuGet, které dříve podporovaly Xamarin.iOS prostřednictvím klasického rozhraní API, publikovaly svá sestavení pomocí monikeru platformy Monotouch10 .
Jednotné rozhraní API zavádí nový identifikátor platformy pro kompatibilní balíčky – Xamarin.iOS10. Stávající balíčky NuGet bude potřeba aktualizovat, aby se přidala podpora pro tuto platformu, a to sestavením v rámci sjednoceného rozhraní API.
Důležité
Pokud ve formuláři "Chyba 3 nemůže obsahovat monotouch.dll" i "Xamarin.iOS.dll" ve stejném projektu Xamarin.iOS – na Xamarin.iOS.dll se odkazuje explicitně, zatímco "monotouch.dll" se po převodu aplikace na sjednocená rozhraní API odkazuje na xxx, Version=0.0.000, Culture=neutral, PublicKeyToken=null, obvykle je to způsobeno tím, že v projektu, který nebyl aktualizován na sjednocené rozhraní API, buď komponentu, nebo balíček NuGet. Budete muset odebrat existující komponentu nebo NuGet, aktualizovat na verzi, která podporuje sjednocená rozhraní API, a provést čisté sestavení.
Cesta k 64 bitům
Základní informace o podpoře 32bitových a 64bitových aplikací a informací o architekturách najdete v 32bitových a 64bitových aspektech platformy.
Nové datové typy
V jádru rozdílu používají rozhraní API pro Mac i iOS datové typy specifické pro architekturu, které jsou vždy 32bitové na 32bitových platformách a 64bitové na 64bitových platformách.
Například Objective-C mapuje NSInteger
datový typ na int32_t
32bitové systémy a na int64_t
64bitové systémy.
Abychom toto chování odpovídali, nahradíme v našem sjednoceném rozhraní API předchozí použití int
(které je v .NET definováno jako vždy System.Int32
) na nový datový typ: System.nint
. "n" si můžete představit jako "nativní", takže nativní celočíselnou typ platformy.
Zavádíme nint
nuint
a nfloat
také poskytujeme datové typy založené na nich, pokud je to potřeba.
Další informace o těchtozměnách
Zjištění architektury aplikací pro iOS
V situacích, kdy vaše aplikace potřebuje vědět, jestli běží na 32bitovém nebo 64bitovém systému iOS. Ke kontrole architektury je možné použít následující kód:
if (IntPtr.Size == 4) {
Console.WriteLine ("32-bit App");
} else if (IntPtr.Size == 8) {
Console.WriteLine ("64-bit App");
}
Pole a System.Collections.Generic
Vzhledem k tomu, že indexery jazyka C# očekávají typ int
, budete muset explicitně přetypovat nint
hodnoty int
pro přístup k prvkům v kolekci nebo poli. Příklad:
public List<string> Names = new List<string>();
...
public string GetName(nint index) {
return Names[(int)index];
}
Toto je očekávané chování, protože přetypování z int
na nint
64 bitů je ztráta, implicitní převod se neprovede.
Převod data a času na NSDate
Při použití sjednocených rozhraní API se implicitní převod na DateTime
NSDate
hodnoty už neprovádí. Tyto hodnoty bude nutné explicitně převést z jednoho typu na jiný. K automatizaci tohoto procesu je možné použít následující metody rozšíření:
public static DateTime NSDateToDateTime(this NSDate date)
{
// NSDate has a wider range than DateTime, so clip
// the converted date to DateTime.Min|MaxValue.
double secs = date.SecondsSinceReferenceDate;
if (secs < -63113904000)
return DateTime.MinValue;
if (secs > 252423993599)
return DateTime.MaxValue;
return (DateTime) date;
}
public static NSDate DateTimeToNSDate(this DateTime date)
{
if (date.Kind == DateTimeKind.Unspecified)
date = DateTime.SpecifyKind (date, /* DateTimeKind.Local or DateTimeKind.Utc, this depends on each app */)
return (NSDate) date;
}
Zastaralá rozhraní API a překlepy
V klasickém rozhraní API Xamarin.iOS (monotouch.dll) [Obsolete]
byl atribut použit dvěma různými způsoby:
- Zastaralé rozhraní API pro iOS: Toto je, když vám Apple napoví, že vám přestane používat rozhraní API, protože ho nahrazuje novější. Klasické rozhraní API je stále v pořádku a často se vyžaduje (pokud podporujete starší verzi iOS).
Toto rozhraní API (a
[Obsolete]
atribut) je součástí nových sestavení Xamarin.iOS. - Nesprávné rozhraní API Některé rozhraní API mělo na jejich názvech překlepy.
Pro původní sestavení (monotouch.dll a XamMac.dll) jsme zachovali starý kód dostupný kvůli kompatibilitě, ale odebrali jsme je ze sestavení sjednoceného rozhraní API (Xamarin.iOS.dll a Xamarin.Mac).
Podtřídy NSObject .ctor(IntPtr)
Každá NSObject
podtřída má konstruktor, který přijímá .IntPtr
Takto můžeme vytvořit instanci nové spravované instance z nativního popisovače ObjC.
V klasickém public
prostředí to byl konstruktor. Bylo však snadné tuto funkci zneužít v uživatelském kódu, například vytvořit několik spravovaných instancí pro jednu instanci ObjC nebo vytvořit spravovanou instanci, která by neměla očekávaný spravovaný stav (pro podtřídy).
Aby se zabránilo těmto problémům IntPtr
, konstruktory jsou teď protected
ve sjednoceném rozhraní API, aby se používaly pouze pro podtřídy. Tím zajistíte, že se k vytvoření spravované instance z popisovačů použije správné/bezpečné rozhraní API, tj.
var label = Runtime.GetNSObject<UILabel> (handle);
Toto rozhraní API vrátí existující spravovanou instanci (pokud už existuje) nebo vytvoří novou instanci (pokud je potřeba). Je již k dispozici v klasickém i sjednoceném rozhraní API.
Všimněte si, že .ctor(NSObjectFlag)
je to nyní také protected
, ale tato byla zřídka použita mimo podtřídy.
Akce NSAction nahrazena akcí
U sjednocených rozhraní API NSAction
byla odstraněna ve prospěch standardního rozhraní .NET Action
. Jedná se o velké zlepšení, protože Action
se jedná o běžný typ .NET, zatímco NSAction
byl specifický pro Xamarin.iOS. Oba dělají naprosto stejnou věc, ale byly odlišné a nekompatibilní typy a výsledkem bylo zapsat více kódu, aby bylo možné dosáhnout stejného výsledku.
Pokud například vaše stávající aplikace Xamarin obsahovala následující kód:
UITapGestureRecognizer singleTap = new UITapGestureRecognizer (new NSAction (delegate() {
ShowDropDownAnimated (tblDataView);
}));
Teď ho můžete nahradit jednoduchým výrazem lambda:
UITapGestureRecognizer singleTap = new UITapGestureRecognizer (() => ShowDropDownAnimated(tblDataView));
Dříve to byla chyba kompilátoru, protože Action
nelze přiřadit NSAction
, ale vzhledem k tomu UITapGestureRecognizer
, že teď trvá místo Action
toho NSAction
, aby byla platná v sjednocených rozhraních API.
Vlastní delegáti nahrazeni akcí<T>
Ve sjednocené jednotce byly nahrazeny některé jednoduché delegáty .net (např. jedním parametrem).Action<T>
Například
public delegate void NSNotificationHandler (NSNotification notification);
lze nyní použít jako Action<NSNotification>
. Tím se zvýší opětovné použití kódu a omezení duplicit kódu v Xamarin.iOS i ve vašich vlastních aplikacích.
Logická hodnota> úkolu<nahrazena logickou hodnotou úkolu<, NSError>>
V klasickém prostředí došlo k vrácení Task<bool>
některých asynchronních rozhraní API . Ale některé z nich, kde se mají použít, když NSError
byl součástí podpisu, tj. bool
již byl true
a vy jste museli zachytit výjimku, aby se zobrazila NSError
.
Vzhledem k tomu, že některé chyby jsou velmi běžné a návratová hodnota nebyla užitečná, tento vzor byl změněn ve sjednocené vrátit Task<Tuple<Boolean,NSError>>
. To vám umožní zkontrolovat úspěch i jakoukoli chybu, ke které mohlo dojít během asynchronního volání.
NSString vs řetězec
V několika případech musely být některé konstanty změněny z string
na NSString
, např. UITableViewCell
Klasické
public virtual string ReuseIdentifier { get; }
Jednotný
public virtual NSString ReuseIdentifier { get; }
Obecně dáváme přednost typu .NET System.String
. I přes pokyny Apple ale některé nativní rozhraní API porovnávají konstantní ukazatele (nikoli samotný řetězec) a to může fungovat pouze v případě, že zveřejníme konstanty jako NSString
.
Objective-C Protokoly
Původní MonoTouch neměl úplnou podporu pro protokoly ObjC a některé, neoptimální, rozhraní API bylo přidáno pro podporu nejběžnějšího scénáře. Toto omezení již neexistuje, ale kvůli zpětné kompatibilitě se několik rozhraní API uchovává uvnitř monotouch.dll
a XamMac.dll
.
Tato omezení byla odebrána a vyčištěna u sjednocených rozhraní API. Většina změn bude vypadat takto:
Klasické
public virtual AVAssetResourceLoaderDelegate Delegate { get; }
Jednotný
public virtual IAVAssetResourceLoaderDelegate Delegate { get; }
Předpona I
znamená jednotné zveřejnění rozhraní místo konkrétního typu pro protokol ObjC. Tím se zjednoduší případy, kdy nechcete podtřídět konkrétní typ, který poskytuje Xamarin.iOS.
Některé rozhraní API také umožnilo přesnější a snadno použitelné rozhraní API, například:
Klasické
public virtual void SelectionDidChange (NSObject uiTextInput);
Jednotný
public virtual void SelectionDidChange (IUITextInput uiTextInput);
Toto rozhraní API je teď pro nás jednodušší, aniž byste museli odkazovat na dokumentaci, a dokončování kódu IDE vám poskytne užitečnější návrhy založené na protokolu nebo rozhraní.
Protokol NSCoding
Naše původní vazba obsahovala .ctor(NSCoder) pro každý typ – i když protokol nepodporuje NSCoding
. V kódování objektu NSObject
byla přítomna jedna Encode(NSCoder)
metoda.
Tato metoda by ale fungovala pouze v případě, že instance odpovídá protokolu NSCoding.
U sjednoceného rozhraní API jsme to vyřešili. Nová sestavení budou mít .ctor(NSCoder)
pouze v případě, že typ odpovídá NSCoding
. Takové typy teď mají také metodu Encode(NSCoder)
, která odpovídá INSCoding
rozhraní.
Nízký dopad: Ve většině případů tato změna neovlivní aplikace jako staré, odebrané, konstruktory nelze použít.
Další Tipy
Další změny, o které je potřeba vědět, najdete v tipech pro aktualizaci aplikací na sjednocené rozhraní API.