Ujednolicony interfejs API — omówienie
Ujednolicony interfejs API platformy Xamarin umożliwia udostępnianie kodu między komputerami Mac i iOS oraz obsługą aplikacji 32 i 64-bitowych przy użyciu tego samego pliku binarnego. Ujednolicony interfejs API jest domyślnie używany w nowych projektach platform Xamarin.iOS i Xamarin.Mac.
Ważne
Klasyczny interfejs API platformy Xamarin, który poprzedzał ujednolicony interfejs API, został przestarzały.
- Ostatnia wersja platformy Xamarin.iOS do obsługi klasycznego interfejsu API (monotouch.dll) to Xamarin.iOS 9.10.
- Platforma Xamarin.Mac nadal obsługuje klasyczny interfejs API, ale nie jest już aktualizowany. Ponieważ jest przestarzała, deweloperzy powinni przenieść swoje aplikacje do ujednoliconego interfejsu API.
Aktualizowanie klasycznych aplikacji opartych na interfejsie API
Postępuj zgodnie z odpowiednimi instrukcjami dotyczącymi platformy:
- Aktualizowanie istniejących aplikacji
- Aktualizowanie istniejących aplikacji dla systemu iOS
- Aktualizowanie istniejących aplikacji dla komputerów Mac
- Aktualizowanie istniejących aplikacji rozszerzenia Xamarin.Forms
- Migrowanie powiązania do ujednoliconego interfejsu API
Porady dotyczące aktualizowania kodu na potrzeby ujednoliconego interfejsu API
Niezależnie od migrowanych aplikacji zapoznaj się z tymi wskazówkami , aby ułatwić pomyślną aktualizację do ujednoliconego interfejsu API.
Podział biblioteki
Od tego momentu nasze interfejsy API będą udostępniane na dwa sposoby:
- Klasyczny interfejs API: ograniczony do 32-bitowych (tylko) i uwidoczniony w
monotouch.dll
zestawach iXamMac.dll
. - Ujednolicony interfejs API: obsługa programowania w wersji 32 i 64-bitowej przy użyciu pojedynczego interfejsu API dostępnego
Xamarin.iOS.dll
w zestawach iXamarin.Mac.dll
.
Oznacza to, że w przypadku deweloperów w przedsiębiorstwie (nie przeznaczonych dla sklepu App Store) możesz nadal korzystać z istniejących klasycznych interfejsów API, ponieważ zachowamy je na zawsze lub możesz uaktualnić do nowych interfejsów API.
Zmiany przestrzeni nazw
Aby zmniejszyć problemy z udostępnianiem kodu między naszymi produktami dla komputerów Mac i iOS, zmieniamy przestrzenie nazw dla interfejsów API w produktach.
Usuwamy prefiks "MonoTouch" z naszego produktu dla systemu iOS i "MonoMac" z naszego produktu Mac na typach danych.
Ułatwia to udostępnianie kodu między platformami Mac i iOS bez uciekania się do kompilacji warunkowej i zmniejsza szum u góry plików kodu źródłowego.
- Klasyczny interfejs API: przestrzenie nazw używają
MonoTouch.
lubMonoMac.
prefiksu. - Ujednolicony interfejs API: brak prefiksu przestrzeni nazw
Ustawienia domyślne środowiska uruchomieniowego
Ujednolicony interfejs API domyślnie używa modułu odśmiecania pamięci SGen i systemu zliczania nowych odwołań do śledzenia własności obiektu. Ta sama funkcja została przekierowana do platformy Xamarin.Mac.
Rozwiązuje to szereg problemów, z którymi deweloperzy borykają się ze starym systemem, a także ułatwiają zarządzanie pamięcią.
Należy pamiętać, że istnieje możliwość włączenia polecenia New Refcount nawet dla klasycznego interfejsu API, ale ustawienie domyślne jest konserwatywne i nie wymaga od użytkowników wprowadzania żadnych zmian. Dzięki ujednoliconemu interfejsowi API skorzystaliśmy z okazji zmiany wartości domyślnej i udostępniliśmy deweloperom wszystkie ulepszenia w tym samym czasie, że refaktoryzują i ponownie przetestują swój kod.
Zmiany interfejsu API
Ujednolicony interfejs API usuwa przestarzałe metody i istnieje kilka wystąpień, w których w nazwach interfejsów API znajdowały się literówki, gdy były one powiązane z oryginalnymi przestrzeniami nazw MonoTouch i MonoMac w klasycznych interfejsach API. Te wystąpienia zostały poprawione w nowych ujednoliconych interfejsach API i należy je zaktualizować w składniku, aplikacjach dla systemów iOS i Mac. Oto lista najczęściej używanych elementów, na które można napotkać:
Nazwa klasycznej metody interfejsu API | Ujednolicona nazwa metody interfejsu 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 |
Pełną listę zmian podczas przełączania z wersji klasycznej do ujednoliconego interfejsu API można znaleźć w naszej dokumentacji różnic między interfejsami API klasycznymi (monotouch.dll) a Ujednoliconymi (Xamarin.iOS.dll).
Aktualizowanie do ujednoliconej
Kilka starych/uszkodzonych/przestarzałych interfejsów API w wersji klasycznej nie jest dostępnych w ujednoliconym interfejsie API. Przed rozpoczęciem uaktualniania (ręcznego lub zautomatyzowanego) można łatwiej naprawić CS0616
ostrzeżenia, ponieważ będziesz mieć komunikat atrybutu [Obsolete]
(część ostrzeżenia), aby poprowadzić Cię do odpowiedniego interfejsu API.
Należy pamiętać, że publikujemy różnice klasycznych i ujednoliconych zmian interfejsu API, które mogą być używane przed aktualizacjami projektu lub po nim. Nadal naprawianie przestarzałych wywołań w wersji klasycznej często będzie oszczędność czasu (mniej odnośników dokumentacji).
Postępuj zgodnie z tymi instrukcjami, aby zaktualizować istniejące aplikacje systemu iOS lub aplikacje dla komputerów Mac do ujednoliconego interfejsu API. Przejrzyj pozostałą część tej strony i te porady , aby uzyskać dodatkowe informacje na temat migracji kodu.
NuGet
Pakiety NuGet, które wcześniej obsługiwały platformę Xamarin.iOS za pośrednictwem klasycznego interfejsu API, opublikowały swoje zestawy przy użyciu pseudonimu platformy Monotouch10 .
Ujednolicony interfejs API wprowadza nowy identyfikator platformy dla zgodnych pakietów — Xamarin.iOS10. Aby dodać obsługę tej platformy, należy zaktualizować istniejące pakiety NuGet, tworząc interfejs API Unified.
Ważne
Jeśli wystąpi błąd w formularzu "Błąd 3 Nie można dołączyć zarówno "monotouch.dll" jak i "Xamarin.iOS.dll" w tym samym projekcie platformy Xamarin.iOS — "Xamarin.iOS.dll" jest jawnie przywołyny. Podczas gdy element "monotouch.dll" jest przywołyany przez element "xxx, Version=0.0.000, Culture=neutral, PublicKeyToken=null" po przekonwertowaniu aplikacji na ujednolicone interfejsy API, zwykle wynika to z posiadania składnika lub pakietu NuGet w projekcie, który nie został zaktualizowany do ujednoliconego interfejsu API. Musisz usunąć istniejący składnik/NuGet, zaktualizować go do wersji obsługującej ujednolicone interfejsy API i wykonać czystą kompilację.
Droga do 64 bitów
Aby zapoznać się z informacjami na temat obsługi aplikacji 32-bitowych i 64-bitowych oraz informacji o strukturach, zobacz zagadnienia dotyczące platformy 32 i 64-bitowej.
Nowe typy danych
Na podstawie różnicy interfejsy API dla komputerów Mac i iOS używają typów danych specyficznych dla architektury, które są zawsze 32-bitowe na platformach 32-bitowych i 64-bitowych na platformach 64-bitowych.
Na przykład Objective-C mapuje NSInteger
typ danych na int32_t
w systemach 32-bitowych i int64_t
na systemy 64-bitowe.
Aby dopasować to zachowanie, w naszym ujednoliconym interfejsie API zastępujemy poprzednie zastosowania int
(które na platformie .NET są zdefiniowane jako zawsze System.Int32
) na nowy typ danych: System.nint
. Możesz traktować "n" jako "natywny", więc natywny typ liczby całkowitej platformy.
Wprowadzamy nint
usługę , nuint
a nfloat
także udostępniamy typy danych oparte na nich w razie potrzeby.
Aby dowiedzieć się więcej na temat tych zmian typów danych, zobacz dokument Native Types (Typy natywne).
Jak wykryć architekturę aplikacji systemu iOS
Mogą wystąpić sytuacje, w których aplikacja musi wiedzieć, czy działa w 32-bitowym lub 64-bitowym systemie iOS. Do sprawdzenia architektury można użyć następującego kodu:
if (IntPtr.Size == 4) {
Console.WriteLine ("32-bit App");
} else if (IntPtr.Size == 8) {
Console.WriteLine ("64-bit App");
}
Tablice i System.Collections.Generic
Ponieważ indeksatory języka C# oczekują typu int
, należy jawnie rzutować nint
wartości, aby uzyskać dostęp do int
elementów w kolekcji lub tablicy. Na przykład:
public List<string> Names = new List<string>();
...
public string GetName(nint index) {
return Names[(int)index];
}
Jest to oczekiwane zachowanie, ponieważ rzutowanie z int
do nint
jest straty na 64 bity, niejawna konwersja nie jest wykonywana.
Konwertowanie daty/godziny na NSDate
W przypadku korzystania z ujednoliconych interfejsów API niejawna konwersja DateTime
wartości NSDate
nie jest już wykonywana. Te wartości będą musiały zostać jawnie przekonwertowane z jednego typu na inny. Następujące metody rozszerzenia mogą służyć do automatyzacji tego procesu:
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;
}
Przestarzałe interfejsy API i literówki
W klasycznym interfejsie API platformy Xamarin.iOS (monotouch.dll) [Obsolete]
atrybut został użyty na dwa różne sposoby:
- Przestarzały interfejs API systemu iOS: jest to, gdy firma Apple wskazuje, że przestanie używać interfejsu API, ponieważ jest zastępowany przez nowsze. Klasyczny interfejs API jest nadal w porządku i często wymagany (jeśli obsługujesz starszą wersję systemu iOS).
Taki interfejs API (i
[Obsolete]
atrybut) są uwzględniane w nowych zestawach platformy Xamarin.iOS. - Niepoprawny interfejs API Niektórzy interfejs API mieli literówki w swoich nazwach.
W przypadku oryginalnych zestawów (monotouch.dll i XamMac.dll) zachowaliśmy stary kod dostępny pod kątem zgodności, ale zostały usunięte z zestawów ujednoliconego interfejsu API (Xamarin.iOS.dll i Xamarin.Mac)
Podklasy NSObject .ctor(IntPtr)
Każda NSObject
podklasa ma konstruktor, który akceptuje element IntPtr
. W ten sposób można utworzyć wystąpienie nowego wystąpienia zarządzanego z natywnego dojścia ObjC.
W wersji klasycznej public
był to konstruktor. Jednak łatwo było niewłaściwego użycia tej funkcji w kodzie użytkownika, np. utworzenie kilku wystąpień zarządzanych dla pojedynczego wystąpienia objC lub utworzenie wystąpienia zarządzanego, które nie będzie miało oczekiwanego stanu zarządzanego (w przypadku podklas).
Aby uniknąć tego rodzaju problemów, IntPtr
konstruktory są teraz protected
w ujednoliconym interfejsie API, które mają być używane tylko do podklasy. Zapewni to, że prawidłowy/bezpieczny interfejs API jest używany do tworzenia wystąpienia zarządzanego na podstawie dojść, tj.
var label = Runtime.GetNSObject<UILabel> (handle);
Ten interfejs API zwróci istniejące wystąpienie zarządzane (jeśli już istnieje) lub utworzy nowe (jeśli jest wymagane). Jest już dostępny w klasycznym i ujednoliconym interfejsie API.
Należy pamiętać, że .ctor(NSObjectFlag)
element jest teraz również, protected
ale ten był rzadko używany poza podklasą.
NSAction zastąpiona akcją
Dzięki ujednoliconym interfejsom NSAction
API usunięto standardową platformę .NET Action
. Jest to duża poprawa, ponieważ Action
jest to typowy typ platformy .NET, natomiast NSAction
był specyficzny dla platformy Xamarin.iOS. Obie robią dokładnie to samo, ale były one odrębne i niezgodne typy i spowodowały, że w celu uzyskania tego samego wyniku trzeba napisać więcej kodu.
Jeśli na przykład istniejąca aplikacja platformy Xamarin zawiera następujący kod:
UITapGestureRecognizer singleTap = new UITapGestureRecognizer (new NSAction (delegate() {
ShowDropDownAnimated (tblDataView);
}));
Teraz można go zastąpić prostą lambdą:
UITapGestureRecognizer singleTap = new UITapGestureRecognizer (() => ShowDropDownAnimated(tblDataView));
Wcześniej był to błąd kompilatora, ponieważ Action
nie można przypisać elementu do NSAction
elementu , ale ponieważ UITapGestureRecognizer
teraz Action
zamiast elementu NSAction
jest prawidłowy w ujednoliconych interfejsach API.
Delegaty niestandardowe zastąpione akcją<T>
W ujednoliconym kilku prostych (np. jeden parametr) delegatów platformy .net zostały zastąpione elementem Action<T>
. Na przykład
public delegate void NSNotificationHandler (NSNotification notification);
można teraz używać jako .Action<NSNotification>
To podwyższanie poziomu ponownego użycia kodu i zmniejszanie duplikacji kodu zarówno w środowisku Xamarin.iOS, jak i we własnych aplikacjach.
Wartość logiczna> zadania<została zastąpiona wartością logiczną zadania<, NSError>>
W wersji klasycznej wystąpiły pewne asynchroniczne interfejsy API zwracające Task<bool>
element . Jednak niektóre z nich, gdzie mają być używane, gdy NSError
element był częścią podpisu, tj. bool
był już true
i trzeba było złapać wyjątek, aby uzyskać NSError
.
Ponieważ niektóre błędy są bardzo powszechne i wartość zwracana nie była przydatna, ten wzorzec został zmieniony w ujednolicony , aby zwrócić Task<Tuple<Boolean,NSError>>
wartość . Dzięki temu można sprawdzić powodzenie i wszelkie błędy, które mogły wystąpić podczas wywołania asynchronicznego.
Ciąg NSString a ciąg
W kilku przypadkach niektóre stałe musiały zostać zmienione z string
na NSString
, np. UITableViewCell
Klasyczny
public virtual string ReuseIdentifier { get; }
Unified
public virtual NSString ReuseIdentifier { get; }
Ogólnie rzecz biorąc, preferujemy typ .NET System.String
. Jednak pomimo wytycznych firmy Apple niektóre natywne interfejsy API porównują stałe wskaźniki (a nie sam ciąg) i może to działać tylko wtedy, gdy uwidaczniamy stałe jako NSString
.
Objective-C Protokołów
Oryginalny interfejs MonoTouch nie miał pełnej obsługi protokołów ObjC, a niektóre, nie optymalne, interfejs API zostały dodane do obsługi najbardziej typowego scenariusza. To ograniczenie już nie istnieje, ale w celu zapewnienia zgodności z poprzednimi wersjami kilka interfejsów API jest przechowywanych wewnątrz monotouch.dll
i XamMac.dll
.
Te ograniczenia zostały usunięte i wyczyszczone w ujednoliconych interfejsach API. Większość zmian będzie wyglądać następująco:
Klasyczny
public virtual AVAssetResourceLoaderDelegate Delegate { get; }
Unified
public virtual IAVAssetResourceLoaderDelegate Delegate { get; }
Prefiks I
oznacza ujednolicone uwidacznienie interfejsu zamiast określonego typu dla protokołu ObjC. Ułatwi to przypadki, w których nie chcesz podklasować określonego typu dostarczonego przez platformę Xamarin.iOS.
Ponadto niektóre interfejsy API mogą być bardziej precyzyjne i łatwe w użyciu, np.:
Klasyczny
public virtual void SelectionDidChange (NSObject uiTextInput);
Unified
public virtual void SelectionDidChange (IUITextInput uiTextInput);
Taki interfejs API jest teraz łatwiejszy, bez odwoływania się do dokumentacji, a uzupełnianie kodu IDE zapewni bardziej przydatne sugestie oparte na protokole/interfejsie.
Protokół NSCoding
Nasze oryginalne powiązanie obejmowało obiekt .ctor(NSCoder) dla każdego typu — nawet jeśli nie obsługuje NSCoding
protokołu. Encode(NSCoder)
Pojedyncza metoda była obecna w obiekcie NSObject
w celu zakodowania obiektu.
Jednak ta metoda działałaby tylko wtedy, gdy wystąpienie jest zgodne z protokołem NSCoding.
Rozwiązaliśmy ten problem w ujednoliconym interfejsie API. Nowe zestawy będą miały .ctor(NSCoder)
wartość tylko wtedy, gdy typ jest NSCoding
zgodny z . Ponadto takie typy mają teraz metodę zgodną Encode(NSCoder)
z interfejsem INSCoding
.
Niski wpływ: w większości przypadków ta zmiana nie wpłynie na aplikacje, ponieważ stare, usunięte konstruktory nie mogą być używane.
Dalsze Wskazówki
Dodatkowe zmiany, o których należy pamiętać, są wymienione w poradach dotyczących aktualizowania aplikacji do ujednoliconego interfejsu API.