Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Używanie typów ogólnych z obiektami NSObjects
Można użyć typów ogólnych w podklasach NSObjectklasy , na przykład UIView:
class Foo<T> : UIView {
public Foo (CGRect x) : base (x) {}
public override void Draw (CoreGraphics.CGRect rect)
{
Console.WriteLine ("T: {0}. Type: {1}", typeof (T), GetType ().Name);
}
}
Ponieważ obiekty, które są zarejestrowane w podklasie NSObjectObjective-C w środowisku uruchomieniowym, istnieją pewne ograniczenia co do tego, co jest możliwe w przypadku ogólnych podklas NSObject typów.
Zagadnienia dotyczące ogólnych podklas NSObject
Ten dokument zawiera szczegółowe informacje o ograniczeniach dotyczących ograniczonej obsługi podklas ogólnych klasy NSObjects.
Argumenty typu ogólnego w podpisach składowych
Wszystkie argumenty typu ogólnego w podpisie składowym uwidocznione muszą Objective-C mieć NSObject ograniczenie.
Dobre:
class Generic<T> : NSObject where T: NSObject
{
[Export ("myMethod:")]
public void MyMethod (T value)
{
}
}
Przyczyna: Parametr typu ogólnego jest parametrem NSObject, więc sygnatura myMethod: selektora może być bezpiecznie uwidoczniona Objective-C (zawsze będzie NSObject to lub podklasa).
Złe:
class Generic<T> : NSObject
{
[Export ("myMethod:")]
public void MyMethod (T value)
{
}
}
Przyczyna: nie można utworzyć Objective-C podpisu dla wyeksportowanych elementów członkowskich, które Objective-C mogą wywołać kod, ponieważ podpis będzie się różnić w zależności od dokładnego typu typu Togólnego .
Dobre:
class Generic<T> : NSObject
{
T storage;
[Export ("myMethod:")]
public void MyMethod (NSObject value)
{
}
}
Przyczyna: istnieje możliwość, że argumenty typu ogólnego nie są ograniczone, o ile nie biorą udziału w wyeksportowanym podpisie elementu członkowskiego.
Dobre:
class Generic<T, U> : NSObject where T: NSObject
{
[Export ("myMethod:")]
public void MyMethod (T value)
{
Console.WriteLine (typeof (U));
}
}
PrzyczynaT: parametr wyeksportowany Objective-CMyMethod jest ograniczony jako NSObjecttyp , typ U nie jest częścią podpisu.
Złe:
class Generic<T> : NSObject
{
public T Storage { get; }
public Generic(T value)
{
Storage = value;
}
}
[Register("Foo")]
class Foo: NSView
{
[Export("Test")]
public Generic<int> Test { get; set; } = new Generic<int>(22);
[Export("Test1")]
public Generic<object> Test1 { get; set; } = new Generic<object>(new object());
[Export("Test2")]
public Generic<NSObject> Test2 { get; set; } = new Generic<NSObject>(new NSObject());
}
Przyczynaregistrar: nie obsługuje jeszcze tego scenariusza. Aby uzyskać więcej informacji, zobacz te problemy z usługą GitHub.
Tworzenie wystąpień typów ogólnych z Objective-C
Tworzenie wystąpień typów ogólnych z Objective-C programu jest niedozwolone. Zwykle występuje to, gdy typ zarządzany jest używany w xib lub scenorysie.
Rozważmy tę definicję klasy, która uwidacznia konstruktor, który przyjmuje IntPtr element (sposób konstruowania obiektu języka C# z wystąpienia natywnego Objective-C platformy Xamarin.iOS):
class Generic<T> : NSObject where T : NSObject
{
public Generic () {}
public Generic (IntPtr ptr) : base (ptr) {}
}
Chociaż powyższa konstrukcja jest w porządku, w czasie wykonywania zgłosi wyjątek, jeśli Objective-C spróbuje utworzyć wystąpienie.
Dzieje się tak, ponieważ Objective-C nie ma pojęcia typów ogólnych i nie może określić dokładnego typu ogólnego do utworzenia.
Ten problem można obejść, tworząc wyspecjalizowaną podklasę typu ogólnego. Na przykład:
class Generic<T> : NSObject where T : NSObject
{
public Generic () {}
public Generic (IntPtr ptr) : base (ptr) {}
}
class GenericUIView : Generic<UIView>
{
}
Teraz nie ma już niejednoznaczności, klasa GenericUIView może być używana w xibs lub scenorysach.
Brak obsługi metod ogólnych
Metody ogólne są niedozwolone.
Następujący kod nie zostanie skompilowany:
class MyClass : NSObject
{
[Export ("myMethod")]
public void MyMethod<T> (T argument)
{
}
}
Przyczyna: Nie jest to dozwolone, ponieważ platforma Xamarin.iOS nie wie, jakiego typu należy użyć dla argumentu T typu, gdy metoda jest wywoływana z Objective-C klasy .
Alternatywą jest utworzenie wyspecjalizowanej metody i wyeksportowanie tej metody:
class MyClass : NSObject
{
[Export ("myMethod")]
public void MyUIViewMethod (UIView argument)
{
MyMethod<UIView> (argument);
}
public void MyMethod<T> (T argument)
{
}
}
Nie są dozwolone wyeksportowane statyczne elementy członkowskie
Nie można uwidocznić statycznych elementów członkowskich, Objective-C jeśli są one hostowane w podklasie ogólnej klasy NSObject.
Przykład nieobsługiwanego scenariusza:
class Generic<T> : NSObject where T : NSObject
{
[Export ("myMethod:")]
public static void MyMethod ()
{
}
[Export ("myProperty")]
public static T MyProperty { get; set; }
}
Przyczyna: Podobnie jak metody ogólne, środowisko uruchomieniowe Xamarin.iOS musi wiedzieć, jakiego typu używać dla argumentu Ttypu ogólnego .
Na przykład elementy członkowskie wystąpienia są używane (ponieważ nigdy nie będzie wystąpienia Generic<T>, zawsze będzie Generic<SomeSpecificClass>to ), ale dla statycznych elementów członkowskich te informacje nie są obecne.
Należy pamiętać, że ma to zastosowanie nawet wtedy, gdy element członkowski, którego dotyczy, nie używa argumentu T typu w żaden sposób.
Alternatywą w tym przypadku jest utworzenie wyspecjalizowanej podklasy:
class GenericUIView : Generic<UIView>
{
[Export ("myUIViewMethod")]
public static void MyUIViewMethod ()
{
MyMethod ();
}
[Export ("myProperty")]
public static UIView MyUIViewProperty {
get { return MyProperty; }
set { MyProperty = value; }
}
}
class Generic<T> : NSObject where T : NSObject
{
public static void MyMethod () {}
public static T MyProperty { get; set; }
}
Wydajność
registrar Statyczny element członkowski nie może rozpoznać wyeksportowanego elementu członkowskiego w typie ogólnym w czasie kompilacji, tak jak zwykle, musi być sprawdzany w czasie wykonywania. Oznacza to, że wywoływanie takiej metody z Objective-C metody jest nieco wolniejsze niż wywoływanie elementów członkowskich z klas innych niż ogólne.