Referenzleitfaden zu Bindungstypen
In diesem Dokument wird die Liste der Attribute beschrieben, mit denen Sie Ihre API-Vertragsdateien kommentieren können, um die Bindung und den generierten Code zu steuern.
Xamarin.iOS- und Xamarin.Mac-API-Verträge werden in C# hauptsächlich als Schnittstellendefinitionen geschrieben, die definieren, wie Objective-C Code in C# angezeigt wird. Der Prozess umfasst eine Mischung aus Schnittstellendeklarationen sowie einige grundlegende Typdefinitionen, die der API-Vertrag möglicherweise erfordert. Eine Einführung in Bindungstypen finden Sie in unserem Begleithandbuch für BindungsbibliothekenObjective-C.
Typdefinitionen
Syntax:
[BaseType (typeof (BTYPE))
interface MyType : [Protocol1, Protocol2] {
IntPtr Constructor (string foo);
}
Jede Schnittstelle in Ihrer Vertragsdefinition, die das [BaseType]
Attribut enthält, deklariert den Basistyp für das generierte Objekt. In der obigen Deklaration wird ein MyType
C#-Klassentyp generiert, der an einen Objective-C aufgerufenen MyType
Typ gebunden wird.
Wenn Sie Typen nach dem Typnamen (im obigen Protocol1
Beispiel und Protocol2
) mithilfe der Schnittstellenvererbungssyntax angeben, werden die Inhalte dieser Schnittstellen inlineiert, als wären sie Teil des Vertrags für MyType
.
Die Art und Weise, wie Xamarin.iOS ein Protokoll verwendet, besteht darin, alle Methoden und Eigenschaften, die im Protokoll deklariert wurden, in den Typ selbst einzugliedern.
Im Folgenden wird gezeigt, wie die Objective-C Deklaration für UITextField
einen Xamarin.iOS-Vertrag definiert wird:
@interface UITextField : UIControl <UITextInput> {
}
Würde wie dieser als C#-API-Vertrag geschrieben werden:
[BaseType (typeof (UIControl))]
interface UITextField : UITextInput {
}
Sie können viele andere Aspekte der Codegenerierung steuern, indem Sie andere Attribute auf die Schnittstelle anwenden und das [BaseType]
Attribut konfigurieren.
Generieren von Ereignissen
Ein Feature des Entwurfs der Xamarin.iOS- und Xamarin.Mac-API besteht darin, dass Stellvertretungsklassen als C#-Ereignisse und Rückrufe zugeordnet Objective-C werden. Benutzer können auf Instanzbasis auswählen, ob sie das Objective-C Programmiermuster übernehmen möchten, indem sie Eigenschaften wie Delegate
eine Instanz einer Klasse zuweisen, die die verschiedenen Methoden implementiert, die die Objective-C Laufzeit aufrufen würde, oder indem sie die C#-Stil-Ereignisse und -Eigenschaften auswählen.
Sehen wir uns ein Beispiel für die Verwendung des Objective-C Modells an:
bool MakeDecision ()
{
return true;
}
void Setup ()
{
var scrollView = new UIScrollView (myRect);
scrollView.Delegate = new MyScrollViewDelegate ();
...
}
class MyScrollViewDelegate : UIScrollViewDelegate {
public override void Scrolled (UIScrollView scrollView)
{
Console.WriteLine ("Scrolled");
}
public override bool ShouldScrollToTop (UIScrollView scrollView)
{
return MakeDecision ();
}
}
Im obigen Beispiel können Sie sehen, dass wir zwei Methoden überschreiben möchten, eine Benachrichtigung, dass ein Bildlaufereignis stattgefunden hat, und die zweite, bei der es sich um einen Rückruf handelt, der einen booleschen Wert zurückgeben soll, der anweist scrollView
, ob er nach oben scrollen soll oder nicht.
Mit dem C#-Modell kann der Benutzer Ihrer Bibliothek Benachrichtigungen mithilfe der C#-Ereignissyntax oder der Eigenschaftssyntax abhören, um Rückrufe zu verbinden, die erwartet werden, dass Werte zurückgegeben werden.
So sieht der C#-Code für das gleiche Feature wie die Verwendung von Lambdas aus:
void Setup ()
{
var scrollview = new UIScrollView (myRect);
// Event connection, use += and multiple events can be connected
scrollView.Scrolled += (sender, eventArgs) { Console.WriteLine ("Scrolled"); }
// Property connection, use = only a single callback can be used
scrollView.ShouldScrollToTop = (sv) => MakeDecision ();
}
Da Ereignisse keine Werte zurückgeben (sie haben einen ungültigen Rückgabetyp), können Sie mehrere Kopien verbinden. Dies ShouldScrollToTop
ist kein Ereignis, sondern eine Eigenschaft mit dem Typ UIScrollViewCondition
, der diese Signatur aufweist:
public delegate bool UIScrollViewCondition (UIScrollView scrollView);
Es gibt einen bool
Wert zurück, in diesem Fall ermöglicht uns die Lambda-Syntax, einfach den Wert aus der MakeDecision
Funktion zurückzugeben.
Der Bindungsgenerator unterstützt das Generieren von Ereignissen und Eigenschaften, die eine Klasse wie UIScrollView
die UIScrollViewDelegate
Model-Klasse verknüpfen (rufen Sie diese gut auf, indem Sie Ihre [BaseType]
Definition mit den und Delegates
den Events
Parametern (siehe unten) kommentieren.
Zusätzlich zur Anmerkungen [BaseType]
zu diesen Parametern ist es notwendig, den Generator über einige weitere Komponenten zu informieren.
Bei Ereignissen, die mehrere Parameter annehmen (in Objective-C der Konvention ist der erste Parameter in einer Delegatenklasse die Instanz des Absenderobjekts), müssen Sie den Namen angeben, den Sie für die generierte EventArgs
Klasse verwenden möchten. Dies erfolgt mit dem [EventArgs]
Attribut für die Methodendeklaration in Ihrer Model-Klasse. Zum Beispiel:
[BaseType (typeof (UINavigationControllerDelegate))]
[Model][Protocol]
public interface UIImagePickerControllerDelegate {
[Export ("imagePickerController:didFinishPickingImage:editingInfo:"), EventArgs ("UIImagePickerImagePicked")]
void FinishedPickingImage (UIImagePickerController picker, UIImage image, NSDictionary editingInfo);
}
Die obige Deklaration generiert eine UIImagePickerImagePickedEventArgs
Klasse, die von EventArgs
beiden Parametern, dem UIImage
und dem Paket NSDictionary
abgeleitet wird. Der Generator erzeugt folgendes:
public partial class UIImagePickerImagePickedEventArgs : EventArgs {
public UIImagePickerImagePickedEventArgs (UIImage image, NSDictionary editingInfo);
public UIImage Image { get; set; }
public NSDictionary EditingInfo { get; set; }
}
Anschließend wird Folgendes in der UIImagePickerController
Klasse verfügbar gemacht:
public event EventHandler<UIImagePickerImagePickedEventArgs> FinishedPickingImage { add; remove; }
Modellmethoden, die einen Wert zurückgeben, sind unterschiedlich gebunden. Diese erfordern sowohl einen Namen für den generierten C#-Delegaten (die Signatur für die Methode) als auch einen Standardwert, der zurückgegeben werden soll, falls der Benutzer keine Implementierung bereitstellt.
Die Definition lautet z. B ShouldScrollToTop
. wie folgt:
[BaseType (typeof (NSObject))]
[Model][Protocol]
public interface UIScrollViewDelegate {
[Export ("scrollViewShouldScrollToTop:"), DelegateName ("UIScrollViewCondition"), DefaultValue ("true")]
bool ShouldScrollToTop (UIScrollView scrollView);
}
In der obigen Tabelle wird eine UIScrollViewCondition
Stellvertretung mit der oben gezeigten Signatur erstellt, und wenn der Benutzer keine Implementierung bereitstellt, ist der Rückgabewert "true".
Zusätzlich zum [DefaultValue]
Attribut können Sie auch das [DefaultValueFromArgument]
Attribut verwenden, das den Generator anweist, um den Wert des angegebenen Parameters im Aufruf oder den Parameter zurückzugeben, der [NoDefaultValue]
den Generator anweist, dass kein Standardwert vorhanden ist.
BaseTypeAttribute
Syntax:
public class BaseTypeAttribute : Attribute {
public BaseTypeAttribute (Type t);
// Properties
public Type BaseType { get; set; }
public string Name { get; set; }
public Type [] Events { get; set; }
public string [] Delegates { get; set; }
public string KeepRefUntil { get; set; }
}
BaseType.Name
Sie verwenden die Name
Eigenschaft, um den Namen zu steuern, an den dieser Typ in der Objective-C Welt gebunden wird. Dies wird in der Regel verwendet, um dem C#-Typ einen Namen zuzuweisen, der mit den .NET Framework-Entwurfsrichtlinien kompatibel ist, die jedoch einem Namen zugeordnet ist, der Objective-C dieser Konvention nicht entspricht.
Im folgenden Fall wird der Objective-CNSURLConnection
Typ NSUrlConnection
zugeordnet, da die .NET Framework-Entwurfsrichtlinien "URL" anstelle von "URL" verwenden:
[BaseType (typeof (NSObject), Name="NSURLConnection")]
interface NSUrlConnection {
}
Der angegebene Name wird als Wert für das generierte [Register]
Attribut in der Bindung verwendet. Wenn Name
nicht angegeben, wird der Kurzname des Typs als Wert für das [Register]
Attribut in der generierten Ausgabe verwendet.
BaseType.Events und BaseType.Delegates
Diese Eigenschaften werden verwendet, um die Generierung von C#-Style-Ereignissen in den generierten Klassen zu steuern. Sie werden verwendet, um eine bestimmte Klasse mit ihrer Objective-C Delegatklasse zu verknüpfen. Es treten viele Fälle auf, in denen eine Klasse eine Delegatklasse zum Senden von Benachrichtigungen und Ereignissen verwendet. Ein Beispiel wäre eine BarcodeScanner
Begleitklasse BardodeScannerDelegate
. Die BarcodeScanner
Klasse verfügt in der Regel über eine Delegate
Eigenschaft, der Sie eine Instanz BarcodeScannerDelegate
zuweisen würden, während dies funktioniert, möchten Sie Ihren Benutzern möglicherweise eine C#-ähnliche Ereignisschnittstelle für Stile verfügbar machen, und in diesen Fällen würden Sie die Events
Eigenschaften Delegates
und Eigenschaften des [BaseType]
Attributs verwenden.
Diese Eigenschaften sind immer miteinander festgelegt und müssen dieselbe Anzahl von Elementen aufweisen und synchron gehalten werden. Das Delegates
Array enthält eine Zeichenfolge für jeden schwach typierten Delegaten, den Sie umbrechen möchten, und das Events
Array enthält einen Typ für jeden Typ, den Sie diesem zuordnen möchten.
[BaseType (typeof (NSObject),
Delegates=new string [] { "WeakDelegate" },
Events=new Type [] {typeof(UIAccelerometerDelegate)})]
public interface UIAccelerometer {
}
[BaseType (typeof (NSObject))]
[Model][Protocol]
public interface UIAccelerometerDelegate {
}
BaseType.KeepRefUntil
Wenn Sie dieses Attribut anwenden, wenn neue Instanzen dieser Klasse erstellt werden, wird die Instanz dieses Objekts beibehalten, bis die Methode, auf die von der KeepRefUntil
Klasse verwiesen wird, aufgerufen wurde. Dies ist nützlich, um die Benutzerfreundlichkeit Ihrer APIs zu verbessern, wenn Sie nicht möchten, dass Der Benutzer einen Verweis auf ein Objekt enthält, um Ihren Code zu verwenden. Der Wert dieser Eigenschaft ist der Name einer Methode in der Delegate
Klasse, daher müssen Sie dies auch in Kombination mit den Events
Eigenschaften verwenden Delegates
.
Das folgende Beispiel zeigt, wie dies von UIActionSheet
Xamarin.iOS verwendet wird:
[BaseType (typeof (NSObject), KeepRefUntil="Dismissed")]
[BaseType (typeof (UIView),
KeepRefUntil="Dismissed",
Delegates=new string [] { "WeakDelegate" },
Events=new Type [] {typeof(UIActionSheetDelegate)})]
public interface UIActionSheet {
}
[BaseType (typeof (NSObject))]
[Model][Protocol]
public interface UIActionSheetDelegate {
[Export ("actionSheet:didDismissWithButtonIndex:"), EventArgs ("UIButton")]
void Dismissed (UIActionSheet actionSheet, nint buttonIndex);
}
DesignatedDefaultCtorAttribute
Wenn dieses Attribut auf die Schnittstellendefinition angewendet wird, generiert es ein [DesignatedInitializer]
Attribut für den Standardkonstruktor (generiert), der dem init
Selektor zugeordnet ist.
DisableDefaultCtorAttribute
Wenn dieses Attribut auf die Schnittstellendefinition angewendet wird, wird verhindert, dass der Generator den Standardkonstruktor erzeugt.
Verwenden Sie dieses Attribut, wenn das Objekt mit einem der anderen Konstruktoren in der Klasse initialisiert werden muss.
PrivateDefaultCtorAttribute
Wenn dieses Attribut auf die Schnittstellendefinition angewendet wird, wird der Standardkonstruktor als privat gekennzeichnet. Dies bedeutet, dass Sie das Objekt dieser Klasse immer noch intern aus Ihrer Erweiterungsdatei instanziieren können, aber sie kann nur für Benutzer Ihrer Klasse zugänglich sein.
CategoryAttribute
Verwenden Sie dieses Attribut für eine Typdefinition, um Kategorien zu binden Objective-C und diese als C#-Erweiterungsmethoden verfügbar zu machen, um die Funktionalität Objective-C zu spiegeln.
Kategorien sind ein Objective-C Mechanismus, der verwendet wird, um den Satz von Methoden und Eigenschaften zu erweitern, die in einer Klasse verfügbar sind. In der Praxis werden sie verwendet, um entweder die Funktionalität einer Basisklasse (z NSObject
. B. ) zu erweitern, wenn ein bestimmtes Framework verknüpft ist (z. B UIKit
. ), indem sie ihre Methoden verfügbar machen, aber nur, wenn das neue Framework verknüpft ist. In einigen anderen Fällen werden sie verwendet, um Features in einer Klasse nach Funktionalität zu organisieren. Sie ähneln den C#-Erweiterungsmethoden.
Dies würde eine Kategorie wie folgt Objective-Caussehen:
@interface UIView (MyUIViewExtension)
-(void) makeBackgroundRed;
@end
Das obige Beispiel befindet sich in einer Bibliothek, die Instanzen der UIView
Methode makeBackgroundRed
erweitern würde.
Um diese zu binden, können Sie das [Category]
Attribut für eine Schnittstellendefinition verwenden. Bei Verwendung des [Category]
Attributs ändert sich die Bedeutung des [BaseType]
Attributs von der Verwendung zum Angeben der zu erweiternden Basisklasse, um den zu erweiternden Typ zu sein.
Im Folgenden wird gezeigt, wie die UIView
Erweiterungen gebunden und in C#-Erweiterungsmethoden umgewandelt werden:
[BaseType (typeof (UIView))]
[Category]
interface MyUIViewExtension {
[Export ("makeBackgroundRed")]
void MakeBackgroundRed ();
}
Im obigen Abschnitt wird eine MyUIViewExtension
Klasse erstellt, die die MakeBackgroundRed
Erweiterungsmethode enthält. Dies bedeutet, dass Sie jetzt eine beliebige UIView
Unterklasse aufrufen MakeBackgroundRed
können, sodass Sie die gleiche Funktionalität erhalten, die Sie erhalten Objective-Cwürden.
In einigen Fällen finden Sie statische Elemente in Kategorien wie im folgenden Beispiel:
@interface FooObject (MyFooObjectExtension)
+ (BOOL)boolMethod:(NSRange *)range;
@end
Dies führt zu einer falschen Definition der Kategorie C#-Schnittstelle:
[Category]
[BaseType (typeof (FooObject))]
interface FooObject_Extensions {
// Incorrect Interface definition
[Static]
[Export ("boolMethod:")]
bool BoolMethod (NSRange range);
}
Dies ist falsch, da Sie die Erweiterung verwenden, die BoolMethod
Sie benötigen, FooObject
aber eine statische ObjC-Erweiterung binden, ist dies ein Nebeneffekt aufgrund der Tatsache, wie C#-Erweiterungsmethoden implementiert werden.
Die einzige Möglichkeit, die obigen Definitionen zu verwenden, ist der folgende hässliche Code:
(null as FooObject).BoolMethod (range);
Die Empfehlung, dies zu vermeiden, besteht darin, die Definition innerhalb der BoolMethod
FooObject
Schnittstellendefinition selbst inline zu setzen. Dadurch können Sie diese Erweiterung wie vorgesehen FooObject.BoolMethod (range)
aufrufen.
[BaseType (typeof (NSObject))]
interface FooObject {
[Static]
[Export ("boolMethod:")]
bool BoolMethod (NSRange range);
}
Es wird eine Warnung (BI1117) ausgegeben, wenn ein [Static]
Mitglied in einer [Category]
Definition gefunden wird. Wenn Sie wirklich Mitglieder in Ihren [Category]
Definitionen haben [Static]
möchten, können Sie die Warnung mithilfe [Category (allowStaticMembers: true)]
oder durch Schmücken Ihrer Member- oder [Category]
Schnittstellendefinition mit [Internal]
stillen.
StaticAttribute
Wenn dieses Attribut auf eine Klasse angewendet wird, generiert es einfach eine statische Klasse, von der eine nicht abgeleitet NSObject
wird, sodass das [BaseType]
Attribut ignoriert wird. Statische Klassen werden verwendet, um öffentliche C-Variablen zu hosten, die Sie verfügbar machen möchten.
Zum Beispiel:
[Static]
interface CBAdvertisement {
[Field ("CBAdvertisementDataServiceUUIDsKey")]
NSString DataServiceUUIDsKey { get; }
Generiert eine C#-Klasse mit der folgenden API:
public partial class CBAdvertisement {
public static NSString DataServiceUUIDsKey { get; }
}
Protokoll-/Modelldefinitionen
Modelle werden in der Regel von der Protokollimplementierung verwendet. Sie unterscheiden sich darin, dass die Laufzeit nur bei Objective-C den Methoden registriert wird, die tatsächlich überschrieben wurden. Andernfalls wird die Methode nicht registriert.
Dies bedeutet im Allgemeinen, dass Sie beim Unterklassen einer Klasse, die mit der ModelAttribute
Basismethode gekennzeichnet wurde, nicht aufrufen sollten. Wenn Sie diese Methode aufrufen, wird die folgende Ausnahme ausgelöst: Foundation.You_Should_Not_Call_base_In_This_Method. Sie sollten das gesamte Verhalten für Ihre Unterklasse für alle Methoden implementieren, die Sie außer Kraft setzen.
AbstractAttribute
Standardmäßig sind Elemente, die Teil eines Protokolls sind, nicht obligatorisch. Auf diese Weise können Benutzer eine Unterklasse des Model
Objekts erstellen, indem sie lediglich von der Klasse in C# abgeleitet und nur die methoden überschrieben werden, die ihnen wichtig sind. Manchmal erfordert der Objective-C Vertrag, dass der Benutzer eine Implementierung für diese Methode bereitstellt (die mit der @required
Direktive gekennzeichnet sind).Objective-C In diesen Fällen sollten Sie diese Methoden mit dem [Abstract]
Attribut kennzeichnen.
Das [Abstract]
Attribut kann entweder auf Methoden oder Eigenschaften angewendet werden und bewirkt, dass der Generator das generierte Element als abstrakt kennzeichnen und die Klasse eine abstrakte Klasse ist.
Es folgt aus Xamarin.iOS:
[BaseType (typeof (NSObject))]
[Model][Protocol]
public interface UITableViewDataSource {
[Export ("tableView:numberOfRowsInSection:")]
[Abstract]
nint RowsInSection (UITableView tableView, nint section);
}
DefaultValueAttribute
Gibt den Standardwert an, der von einer Modellmethode zurückgegeben werden soll, wenn der Benutzer keine Methode für diese bestimmte Methode im Model-Objekt bereitstellt.
Syntax:
public class DefaultValueAttribute : Attribute {
public DefaultValueAttribute (object o);
public object Default { get; set; }
}
In der folgenden imaginären Delegatklasse für eine Camera
Klasse stellen wir beispielsweise eine ShouldUploadToServer
Klasse bereit, die als Eigenschaft für die Camera
Klasse verfügbar gemacht wird. Wenn der Benutzer der Camera
Klasse nicht explizit einen Wert auf eine Lambda-Funktion festlegt, die auf "true" oder "false" reagieren kann, lautet der in diesem Fall zurückgegebene Standardwert "false", der wert, den DefaultValue
wir im Attribut angegeben haben:
[BaseType (typeof (NSObject))]
[Model][Protocol]
interface CameraDelegate {
[Export ("camera:shouldPromptForAction:"), DefaultValue (false)]
bool ShouldUploadToServer (Camera camera, CameraAction action);
}
Wenn der Benutzer einen Handler in der imaginären Klasse festlegt, wird dieser Wert ignoriert:
var camera = new Camera ();
camera.ShouldUploadToServer = (camera, action) => return SomeDecision ();
Siehe auch: [NoDefaultValue]
, [DefaultValueFromArgument]
.
DefaultValueFromArgumentAttribute
Syntax:
public class DefaultValueFromArgumentAttribute : Attribute {
public DefaultValueFromArgumentAttribute (string argument);
public string Argument { get; }
}
Dieses Attribut, wenn es für eine Methode bereitgestellt wird, die einen Wert für eine Modellklasse zurückgibt, weist den Generator an, den Wert des angegebenen Parameters zurückzugeben, wenn der Benutzer keine eigene Methode oder Lambda-Methode bereitgestellt hat.
Beispiel:
[BaseType (typeof (NSObject))]
[Model][Protocol]
public interface NSAnimationDelegate {
[Export ("animation:valueForProgress:"), DelegateName ("NSAnimationProgress"), DefaultValueFromArgumentAttribute ("progress")]
float ComputeAnimationCurve (NSAnimation animation, nfloat progress);
}
Wenn der Benutzer der NSAnimation
Klasse im obigen Fall eines der C#-Ereignisse/-Eigenschaften verwendet hat und nicht auf eine Methode oder Lambda festgelegt NSAnimation.ComputeAnimationCurve
wurde, wäre der Rückgabewert der wert, der im Statusparameter übergeben wird.
Siehe auch: [NoDefaultValue]
, [DefaultValue]
IgnoredInDelegateAttribute
Manchmal ist es sinnvoll, keine Ereignis- oder Delegateigenschaft aus einer Model-Klasse in der Hostklasse verfügbar zu machen, sodass das Hinzufügen dieses Attributs den Generator anweist, um die Generierung von methoden zu vermeiden, die mit ihr versehen sind.
[BaseType (typeof (UINavigationControllerDelegate))]
[Model][Protocol]
public interface UIImagePickerControllerDelegate {
[Export ("imagePickerController:didFinishPickingImage:editingInfo:"), EventArgs ("UIImagePickerImagePicked")]
void FinishedPickingImage (UIImagePickerController picker, UIImage image, NSDictionary editingInfo);
[Export ("imagePickerController:didFinishPickingImage:"), IgnoredInDelegate)] // No event generated for this method
void FinishedPickingImage (UIImagePickerController picker, UIImage image);
}
DelegateNameAttribute
Dieses Attribut wird in Model-Methoden verwendet, die Werte zurückgeben, um den Namen der zu verwendenden Stellvertretungssignatur festzulegen.
Beispiel:
[BaseType (typeof (NSObject))]
[Model][Protocol]
public interface NSAnimationDelegate {
[Export ("animation:valueForProgress:"), DelegateName ("NSAnimationProgress"), DefaultValueFromArgumentAttribute ("progress")]
float ComputeAnimationCurve (NSAnimation animation, float progress);
}
Mit der obigen Definition erzeugt der Generator die folgende öffentliche Deklaration:
public delegate float NSAnimationProgress (MonoMac.AppKit.NSAnimation animation, float progress);
DelegateApiNameAttribute
Dieses Attribut wird verwendet, damit der Generator den Namen der in der Hostklasse generierten Eigenschaft ändern kann. Manchmal ist es nützlich, wenn der Name der FooDelegate-Klassenmethode für die Delegate-Klasse sinnvoll ist, aber in der Hostklasse als Eigenschaft ungerade aussehen würde.
Dies ist auch wirklich nützlich (und erforderlich), wenn Sie über zwei oder mehr Überladungsmethoden verfügen, die sinnvoll sind, sie wie in der FooDelegate-Klasse benannt zu halten, aber Sie möchten sie in der Hostklasse mit einem besseren Vornamen verfügbar machen.
Beispiel:
[BaseType (typeof (NSObject))]
[Model][Protocol]
public interface NSAnimationDelegate {
[Export ("animation:valueForProgress:"), DelegateApiName ("ComputeAnimationCurve"), DelegateName ("Func<NSAnimation, float, float>"), DefaultValueFromArgument ("progress")]
float GetValueForProgress (NSAnimation animation, float progress);
}
Mit der obigen Definition erzeugt der Generator die folgende öffentliche Deklaration in der Hostklasse:
public Func<NSAnimation, float, float> ComputeAnimationCurve { get; set; }
EventArgsAttribute
Für Ereignisse, die mehrere Parameter annehmen (in Objective-C der Konvention ist der erste Parameter in einer Delegatenklasse die Instanz des Senderobjekts), müssen Sie den Namen angeben, den Sie für die generierte EventArgs-Klasse verwenden möchten. Dies geschieht mit dem [EventArgs]
Attribut für die Methodendeklaration in Ihrer Model
Klasse.
Zum Beispiel:
[BaseType (typeof (UINavigationControllerDelegate))]
[Model][Protocol]
public interface UIImagePickerControllerDelegate {
[Export ("imagePickerController:didFinishPickingImage:editingInfo:"), EventArgs ("UIImagePickerImagePicked")]
void FinishedPickingImage (UIImagePickerController picker, UIImage image, NSDictionary editingInfo);
}
Die obige Deklaration generiert eine UIImagePickerImagePickedEventArgs
Klasse, die von EventArgs abgeleitet wird und beide Parameter, die UIImage
und die NSDictionary
. Der Generator erzeugt folgendes:
public partial class UIImagePickerImagePickedEventArgs : EventArgs {
public UIImagePickerImagePickedEventArgs (UIImage image, NSDictionary editingInfo);
public UIImage Image { get; set; }
public NSDictionary EditingInfo { get; set; }
}
Anschließend wird Folgendes in der UIImagePickerController
Klasse verfügbar gemacht:
public event EventHandler<UIImagePickerImagePickedEventArgs> FinishedPickingImage { add; remove; }
EventNameAttribute
Dieses Attribut wird verwendet, um dem Generator das Ändern des Namens eines Ereignisses oder einer Eigenschaft zu ermöglichen, das in der Klasse generiert wird. Manchmal ist es nützlich, wenn der Name der Model-Klassenmethode für die Modellklasse sinnvoll ist, aber in der ursprünglichen Klasse als Ereignis oder Eigenschaft ungerade aussehen würde.
Das folgende Bit wird z UIWebView
. B. aus dem UIWebViewDelegate
Folgenden verwendet:
[Export ("webViewDidFinishLoad:"), EventArgs ("UIWebView"), EventName ("LoadFinished")]
void LoadingFinished (UIWebView webView);
Die oben genannte Methode wird LoadingFinished
als Methode im UIWebViewDelegate
, aber LoadFinished
als Ereignis verfügbar gemacht, mit dem in einem UIWebView
:
var webView = new UIWebView (...);
webView.LoadFinished += delegate { Console.WriteLine ("done!"); }
ModelAttribute
Wenn Sie das [Model]
Attribut auf eine Typdefinition in Der Vertrags-API anwenden, generiert die Laufzeit speziellen Code, der nur Aufrufe für Methoden in der Klasse anzeigt, wenn der Benutzer eine Methode in der Klasse überschrieben hat. Dieses Attribut wird in der Regel auf alle APIs angewendet, die eine Objective-C Delegatklasse umschließen.
Die Laufzeit generiert auch eine Objective-C Klasse, die dem Namen des entsprechenden Protokolls entspricht.
Es ist möglich, den Namen der Objective-C Klasse auf zwei Arten anzupassen:
Einstellung
AutoGeneratedName = true
:[Model (AutoGeneratedName = true)]
Dadurch generiert die Laufzeit einen eindeutigen Namen für den Objective-C Typ. Der Name basiert derzeit auf dem Assemblynamen und dem vollständigen Namen des Typs des Modells (dies kann sich in Zukunft ändern).
Explizite Angabe des Namens:
[Model (Name = "CustomName")]
Es wird empfohlen, die Verwendung zu verwenden AutoGeneratedName = true
. In .NET wird der Name immer generiert (es sei denn, er wird explizit wie in 2. oben angegeben), und die AutoGeneratedName
Eigenschaft ist nicht mehr vorhanden.
NoDefaultValueAttribute
Gibt an, dass die Methode für das Modell keinen Standardwert bereitstellt.
Dies funktioniert mit der Objective-C Laufzeit, indem auf die Objective-C Laufzeitanforderung reagiert false
wird, um festzustellen, ob der angegebene Selektor in dieser Klasse implementiert ist.
[BaseType (typeof (NSObject))]
[Model][Protocol]
interface CameraDelegate {
[Export ("shouldDisplayPopup"), NoDefaultValue]
bool ShouldUploadToServer ();
}
Siehe auch: [DefaultValue]
, [DefaultValueFromArgument]
Protokolle
Das Objective-C Protokollkonzept ist in C# nicht wirklich vorhanden. Protokolle ähneln C#-Schnittstellen, unterscheiden sich jedoch darin, dass nicht alle in einem Protokoll deklarierten Methoden und Eigenschaften von der Klasse implementiert werden müssen, die sie verwendet. Stattdessen sind einige der Methoden und Eigenschaften optional.
Einige Protokolle werden in der Regel als Modellklassen verwendet, diese sollten mithilfe des [Model]
Attributs gebunden werden.
[BaseType (typeof (NSObject))]
[Model, Protocol]
interface MyProtocol {
// Use [Abstract] when the method is defined in the @required section
// of the protocol definition in Objective-C
[Abstract]
[Export ("say:")]
void Say (string msg);
[Export ("listen")]
void Listen ();
}
Ab Xamarin.iOS 7.0 wurde eine neue und verbesserte Protokollbindungsfunktion integriert. Jede Definition, die das [Protocol]
Attribut enthält, generiert tatsächlich drei unterstützende Klassen, die die Art und Weise, wie Sie Protokolle nutzen, erheblich verbessern:
// Full method implementation, contains all methods
class MyProtocol : IMyProtocol {
public void Say (string msg);
public void Listen (string msg);
}
// Interface that contains only the required methods
interface IMyProtocol: INativeObject, IDisposable {
[Export ("say:")]
void Say (string msg);
}
// Extension methods
static class IMyProtocol_Extensions {
public static void Optional (this IMyProtocol this, string msg);
}
}
Die Klassenimplementierung stellt eine vollständige abstrakte Klasse bereit, mit der Sie einzelne Methoden außer Kraft setzen und die vollständige Typsicherheit erhalten können. Da C# jedoch keine mehrfache Vererbung unterstützt, gibt es Szenarien, in denen Sie möglicherweise eine andere Basisklasse benötigen, aber dennoch eine Schnittstelle implementieren möchten.
Hier kommt die generierte Schnittstellendefinition ein. Es handelt sich um eine Schnittstelle mit allen erforderlichen Methoden aus dem Protokoll. Auf diese Weise können Entwickler, die Ihr Protokoll implementieren möchten, lediglich die Schnittstelle implementieren. Die Laufzeit registriert den Typ automatisch bei der Übernahme des Protokolls.
Beachten Sie, dass die Schnittstelle nur die erforderlichen Methoden auflistet und die optionalen Methoden verfügbar macht. Dies bedeutet, dass Klassen, die das Protokoll übernehmen, die vollständige Typüberprüfung für die erforderlichen Methoden erhalten, aber für die optionalen Protokollmethoden auf schwache Typisierung (manuell mithilfe von Exportattributen und übereinstimmende Signatur) zurückgreifen müssen.
Um eine API zu nutzen, die Protokolle verwendet, erstellt das Bindungstool auch eine Erweiterungsmethodeklasse, die alle optionalen Methoden verfügbar macht. Dies bedeutet, dass Sie, solange Sie eine API verwenden, Protokolle mit allen Methoden behandeln können.
Wenn Sie die Protokolldefinitionen in Ihrer API verwenden möchten, müssen Sie Skelett leere Schnittstellen in Ihrer API-Definition schreiben. Wenn Sie myProtocol in einer API verwenden möchten, müssen Sie dies tun:
[BaseType (typeof (NSObject))]
[Model, Protocol]
interface MyProtocol {
// Use [Abstract] when the method is defined in the @required section
// of the protocol definition in Objective-C
[Abstract]
[Export ("say:")]
void Say (string msg);
[Export ("listen")]
void Listen ();
}
interface IMyProtocol {}
[BaseType (typeof(NSObject))]
interface MyTool {
[Export ("getProtocol")]
IMyProtocol GetProtocol ();
}
Die oben genannten Punkte sind erforderlich, da dies zum Zeitpunkt der IMyProtocol
Bindung nicht vorhanden wäre, weshalb Sie eine leere Schnittstelle bereitstellen müssen.
Übernehmen von protokollgenerierten Schnittstellen
Wann immer Sie eine der schnittstellen implementieren, die für die Protokolle generiert werden, wie folgt:
class MyDelegate : NSObject, IUITableViewDelegate {
nint IUITableViewDelegate.GetRowHeight (nint row) {
return 1;
}
}
Die Implementierung für die erforderlichen Schnittstellenmethoden wird mit dem richtigen Namen exportiert, daher entspricht sie folgendem:
class MyDelegate : NSObject, IUITableViewDelegate {
[Export ("getRowHeight:")]
nint IUITableViewDelegate.GetRowHeight (nint row) {
return 1;
}
}
Dies funktioniert für alle erforderlichen Protokollmember, aber es gibt einen Sonderfall mit optionalen Selektoren, die sie kennen sollten.
Optionale Protokollmember werden bei Verwendung der Basisklasse identisch behandelt:
public class UrlSessionDelegate : NSUrlSessionDownloadDelegate {
public override void DidWriteData (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite)
bei Verwendung der Protokollschnittstelle muss jedoch [Export] hinzugefügt werden. Die IDE fügt sie über autoVervollständigen hinzu, wenn Sie sie hinzufügen, beginnend mit der Außerkraftsetzung.
public class UrlSessionDelegate : NSObject, INSUrlSessionDownloadDelegate {
[Export ("URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:")]
public void DidWriteData (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite)
Es gibt einen geringfügigen Verhaltensunterschied zwischen den beiden zur Laufzeit:
- Benutzer der Basisklasse (z. B. NSUrlSessionDownloadDelegate) stellen alle erforderlichen und optionalen Selektoren bereit, die angemessene Standardwerte zurückgeben.
- Benutzer der Schnittstelle (INSUrlSessionDownloadDelegate im Beispiel) reagieren nur auf die angegebenen genauen Selektoren.
Einige seltene Klassen können sich hier anders verhalten. In fast allen Fällen ist es jedoch sicher, beide zu verwenden.
Protokollinlining
Während Sie vorhandene Objective-C Typen binden, die als Übernahme eines Protokolls deklariert wurden, sollten Sie das Protokoll direkt inlineieren. Deklarieren Sie dazu ihr Protokoll lediglich als Schnittstelle ohne [BaseType]
Attribut, und listen Sie das Protokoll in der Liste der Basisschnittstellen für Ihre Schnittstelle auf.
Beispiel:
interface SpeakProtocol {
[Export ("say:")]
void Say (string msg);
}
[BaseType (typeof (NSObject))]
interface Robot : SpeakProtocol {
[Export ("awake")]
bool Awake { get; set; }
}
Memberdefinitionen
Die Attribute in diesem Abschnitt werden auf einzelne Member eines Typs angewendet: Eigenschaften und Methodendeklarationen.
AlignAttribute
Wird verwendet, um den Ausrichtungswert für Eigenschaftsrückgabetypen anzugeben. Bestimmte Eigenschaften verwenden Zeiger auf Adressen, die an bestimmten Grenzen ausgerichtet werden müssen (in Xamarin.iOS geschieht dies z. B. bei einigen GLKBaseEffect
Eigenschaften, die 16-Byte ausgerichtet sein müssen). Sie können diese Eigenschaft verwenden, um den Getter zu dekorieren und den Ausrichtungswert zu verwenden. Dies wird in der Regel zusammen mit den OpenTK.Vector4
Typen OpenTK.Matrix4
verwendet, wenn sie in Objective-C APIs integriert sind.
Beispiel:
public interface GLKBaseEffect {
[Export ("constantColor")]
Vector4 ConstantColor { [Align (16)] get; set; }
}
AppearanceAttribute
Das [Appearance]
Attribut ist auf iOS 5 beschränkt, in dem der Darstellungs-Manager eingeführt wurde.
Das [Appearance]
Attribut kann auf jede Methode oder Eigenschaft angewendet werden, die UIAppearance
am Framework beteiligt ist. Wenn dieses Attribut auf eine Methode oder Eigenschaft in einer Klasse angewendet wird, leitet es den Bindungsgenerator an, um eine stark typierte Darstellungsklasse zu erstellen, die zum Formatieren aller Instanzen dieser Klasse oder der Instanzen verwendet wird, die bestimmten Kriterien entsprechen.
Beispiel:
public interface UIToolbar {
[Export ("setBackgroundImage:forToolbarPosition:barMetrics:")]
[Appearance]
void SetBackgroundImage (UIImage backgroundImage, UIToolbarPosition position, UIBarMetrics barMetrics);
[Export ("backgroundImageForToolbarPosition:barMetrics:")]
[Appearance]
UIImage GetBackgroundImage (UIToolbarPosition position, UIBarMetrics barMetrics);
}
Der obige Code würde den folgenden Code in UIToolbar generieren:
public partial class UIToolbar {
public partial class UIToolbarAppearance : UIView.UIViewAppearance {
public virtual void SetBackgroundImage (UIImage backgroundImage, UIToolbarPosition position, UIBarMetrics barMetrics);
public virtual UIImage GetBackgroundImage (UIToolbarPosition position, UIBarMetrics barMetrics)
}
public static new UIToolbarAppearance Appearance { get; }
public static new UIToolbarAppearance AppearanceWhenContainedIn (params Type [] containers);
}
AutoReleaseAttribute (Xamarin.iOS 5.4)
Verwenden Sie die [AutoReleaseAttribute]
Methoden und Eigenschaften zum Umschließen des Methodenaufrufs für die Methode in einer NSAutoReleasePool
.
Es Objective-C gibt einige Methoden, die Werte zurückgeben, die dem Standardwert NSAutoReleasePool
hinzugefügt werden. Standardmäßig würde dies zu Ihrem Thread NSAutoReleasePool
gehen, da Xamarin.iOS jedoch auch einen Verweis auf Ihre Objekte behält, solange das verwaltete Objekt lebt, möchten Sie möglicherweise keinen zusätzlichen Verweis beibehalten, der NSAutoReleasePool
nur entwässert wird, bis Ihr Thread die Steuerung zum nächsten Thread zurückgibt, oder Sie zur Hauptschleife zurückkehren.
Dieses Attribut wird z. B. auf schwere Eigenschaften (z. B UIImage.FromFile
. ) angewendet, die Objekte zurückgeben, die dem Standard NSAutoReleasePool
hinzugefügt wurden. Ohne dieses Attribut würden die Bilder beibehalten, solange ihr Thread keine Steuerung an die Hauptschleife zurückgibt. Uf your thread was some sort of background downloader that is always alive and waiting for work, the images would never be released.
ForcedTypeAttribute
Dies [ForcedTypeAttribute]
wird verwendet, um die Erstellung eines verwalteten Typs zu erzwingen, auch wenn das zurückgegebene nicht verwaltete Objekt nicht mit dem in der Bindungsdefinition beschriebenen Typ übereinstimmt.
Dies ist nützlich, wenn der in einer Kopfzeile beschriebene Typ nicht mit dem zurückgegebenen Typ der systemeigenen Methode übereinstimmt, z. B. die folgende Objective-C Definition von NSURLSession
:
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
Es stellt klar fest, dass sie eine NSURLSessionDownloadTask
Instanz zurückgeben wird, aber dennoch eine NSURLSessionTask
, die eine Superklasse ist und damit nicht konvertierbar ist NSURLSessionDownloadTask
. Da wir in einem typsicheren Kontext sind, geschieht ein InvalidCastException
Vorgang.
Um die Kopfzeilenbeschreibung einzuhalten und dies InvalidCastException
zu vermeiden, wird dies [ForcedTypeAttribute]
verwendet.
[BaseType (typeof (NSObject), Name="NSURLSession")]
interface NSUrlSession {
[Export ("downloadTaskWithRequest:")]
[return: ForcedType]
NSUrlSessionDownloadTask CreateDownloadTask (NSUrlRequest request);
}
Außerdem [ForcedTypeAttribute]
wird ein boolescher Wert mit dem Namen akzeptiert, der false
standardmäßig [ForcedType (owns: true)]
lautetOwns
. Der owns-Parameter wird verwendet, um der Besitzerrichtlinie für Core Foundation-Objekte zu folgen.
Dies [ForcedTypeAttribute]
ist nur für Parameter, Eigenschaften und Rückgabewerte gültig.
BindAsAttribute
Dies [BindAsAttribute]
ermöglicht die Bindung NSNumber
NSValue
und NSString
(Enumerationen) in genauere C#-Typen. Das Attribut kann verwendet werden, um eine bessere, genauere .NET-API über die systemeigene API zu erstellen.
Sie können Methoden (auf Rückgabewert), Parameter und Eigenschaften mit BindAs
. Die einzige Einschränkung besteht darin, dass sich Ihr Mitglied nicht innerhalb einer [Protocol]
Oder [Model]
Schnittstelle befinden darf.
Zum Beispiel:
[return: BindAs (typeof (bool?))]
[Export ("shouldDrawAt:")]
NSNumber ShouldDraw ([BindAs (typeof (CGRect))] NSValue rect);
Würde folgendes ausgeben:
[Export ("shouldDrawAt:")]
bool? ShouldDraw (CGRect rect) { ... }
Intern werden wir die bool?
<>NSNumber
- und<CGRect
->NSValue
Konvertierungen tun.
Die aktuellen unterstützten Kapselungstypen sind:
NSValue
NSNumber
NSString
NSValue
Die folgenden C#-Datentypen werden unterstützt, um von/in NSValue
gekapselt zu werden:
- CGAffineTransform
- NSRange
- CGVector
- SCNMatrix4
- CLLocationCoordinate2D
- SCNVector3
- SCNVector4
- CGPoint / PointF
- CGRect / RectangleF
- CGSize / SizeF
- UIEdgeInsets
- UIOffset
- MKCoordinateSpan
- CMTimeRange
- CMTime
- CMTimeMapping
- CATransform3D
NSNumber
Die folgenden C#-Datentypen werden unterstützt, um von/in NSNumber
gekapselt zu werden:
- bool
- Byte
- double
- float
- short
- int
- long
- sbyte
- ushort
- uint
- ulong
- nfloat
- nint
- nuint
- Enumerationen
NSString
[BindAs]
funktioniert in Verbindung mit Enumerationen, die von einer NSString-Konstante unterstützt werden, sodass Sie eine bessere .NET-API erstellen können, z. B.:
[BindAs (typeof (CAScroll))]
[Export ("supportedScrollMode")]
NSString SupportedScrollMode { get; set; }
Würde folgendes ausgeben:
[Export ("supportedScrollMode")]
CAScroll SupportedScrollMode { get; set; }
Die Konvertierung wird nur behandeltenum
<NSString
>, wenn der bereitgestellte Enumerationstyp [BindAs]
von einer NSString-Konstante unterstützt wird.
Arrays
[BindAs]
Unterstützt auch Arrays aller unterstützten Typen, Sie können die folgende API-Definition als Beispiel verwenden:
[return: BindAs (typeof (CAScroll []))]
[Export ("getScrollModesAt:")]
NSString [] GetScrollModes ([BindAs (typeof (CGRect []))] NSValue [] rects);
Würde folgendes ausgeben:
[Export ("getScrollModesAt:")]
CAScroll? [] GetScrollModes (CGRect [] rects) { ... }
Der rects
Parameter wird in ein NSArray
Kapselungselement umgewandelt, das eine NSValue
für jedes CGRect
enthält, und im Gegenzug erhalten Sie ein Array, dessen CAScroll?
Werte mit den Werten der zurückgegebenen enthaltenden NSArray
NSStrings
Elemente erstellt wurden.
BindAttribute
Das [Bind]
Attribut hat zwei Verwendungsmöglichkeiten, wenn es auf eine Methode oder Eigenschaftsdeklaration angewendet wird, und ein anderes, wenn es auf den einzelnen Getter oder Setter in einer Eigenschaft angewendet wird.
Bei Verwendung für eine Methode oder Eigenschaft wird durch den Effekt des [Bind]
Attributs eine Methode generiert, die den angegebenen Selektor aufruft. Die resultierende generierte Methode ist jedoch nicht mit dem [Export]
Attribut versehen, was bedeutet, dass sie nicht an der Methodenüberschreibung teilnehmen kann. Dies wird in der Regel in Kombination mit dem Attribut für die [Target]
Implementierung von Objective-C Erweiterungsmethoden verwendet.
Zum Beispiel:
public interface UIView {
[Bind ("drawAtPoint:withFont:")]
SizeF DrawString ([Target] string str, CGPoint point, UIFont font);
}
Bei Verwendung in einem Getter oder Setter wird das [Bind]
Attribut verwendet, um die vom Codegenerator abgeleiteten Standardwerte beim Generieren der Getter- und Settermarkiernamen Objective-C für eine Eigenschaft zu ändern. Wenn Sie eine Eigenschaft mit dem Namen fooBar
kennzeichnen, generiert der Generator standardmäßig einen fooBar
Export für den Getter und setFooBar:
für den Setter. In einigen Fällen Objective-C folgt diese Konvention nicht, in der Regel ändern sie den Getternamen in ".isFooBar
Sie würden dieses Attribut verwenden, um den Generator darüber zu informieren.
Zum Beispiel:
// Default behavior
[Export ("active")]
bool Active { get; set; }
// Custom naming with the Bind attribute
[Export ("visible")]
bool Visible { [Bind ("isVisible")] get; set; }
AsyncAttribute
Nur verfügbar unter Xamarin.iOS 6.3 und höher.
Dieses Attribut kann auf Methoden angewendet werden, die einen Abschlusshandler als letztes Argument verwenden.
Sie können das [Async]
Attribut für Methoden verwenden, deren letztes Argument ein Rückruf ist. Wenn Sie dies auf eine Methode anwenden, generiert der Bindungsgenerator eine Version dieser Methode mit dem Suffix Async
. Wenn der Rückruf keine Parameter akzeptiert, ist der Rückgabewert ein Task
, wenn der Rückruf einen Parameter akzeptiert, ist das Ergebnis ein Task<T>
.
[Export ("upload:complete:")]
[Async]
void LoadFile (string file, NSAction complete)
Im Folgenden wird diese asynchrone Methode generiert:
Task LoadFileAsync (string file);
Wenn der Rückruf mehrere Parameter akzeptiert, sollten Sie den ResultType
gewünschten Namen des generierten Typs festlegen oder ResultTypeName
angeben, der alle Eigenschaften enthält.
delegate void OnComplete (string [] files, nint byteCount);
[Export ("upload:complete:")]
[Async (ResultTypeName="FileLoading")]
void LoadFiles (string file, OnComplete complete)
Im Folgenden wird diese asynchrone Methode generiert, in der FileLoading
Eigenschaften für den Zugriff auf beide files
und byteCount
:
Task<FileLoading> LoadFile (string file);
Wenn der letzte Parameter des Rückrufs ein NSError
Ist, überprüft die generierte Async
Methode, ob der Wert nicht NULL ist, und wenn dies der Fall ist, legt die generierte asynchrone Methode die Task-Ausnahme fest.
[Export ("upload:onComplete:")]
[Async]
void Upload (string file, Action<string,NSError> onComplete);
Im obigen Beispiel wird die folgende asynchrone Methode generiert:
Task<string> UploadAsync (string file);
And on error, the result Task will have the exception set to an NSErrorException
that wraps the result NSError
.
AsyncAttribute.ResultType
Verwenden Sie diese Eigenschaft, um den Wert für das zurückgegebene Task
Objekt anzugeben. Dieser Parameter verwendet einen vorhandenen Typ, daher muss er in einer Ihrer Kern-API-Definitionen definiert werden.
AsyncAttribute.ResultTypeName
Verwenden Sie diese Eigenschaft, um den Wert für das zurückgegebene Task
Objekt anzugeben. Dieser Parameter verwendet den Namen des gewünschten Typnamens, der Generator erzeugt eine Reihe von Eigenschaften, eine für jeden Parameter, den der Rückruf akzeptiert.
AsyncAttribute.MethodName
Verwenden Sie diese Eigenschaft, um den Namen der generierten asynchronen Methoden anzupassen. Der Standardwert ist die Verwendung des Namens der Methode und das Anfügen des Texts "Async", mit dem Sie diese Standardeinstellung ändern können.
DesignatedInitializerAttribute
Wenn dieses Attribut auf einen Konstruktor angewendet wird, generiert es dasselbe [DesignatedInitializer]
in der endgültigen Plattformassembly. Dies soll der IDE helfen, anzugeben, welcher Konstruktor in Unterklassen verwendet werden soll.
Dies sollte Objective-Cder Verwendung von /clang zugeordnet werden __attribute__((objc_designated_initializer))
.
DisableZeroCopyAttribute
Dieses Attribut wird auf Zeichenfolgenparameter oder Zeichenfolgeneigenschaften angewendet und weist den Codegenerator an, für diesen Parameter keine Nullkopie-Zeichenfolgenmarsing zu verwenden, und erstellt stattdessen eine neue NSString-Instanz aus der C#-Zeichenfolge.
Dieses Attribut ist nur für Zeichenfolgen erforderlich, wenn Sie den Generator anweisen, entweder die --zero-copy
Befehlszeilenoption zu verwenden oder das Attribut ZeroCopyStringsAttribute
auf Assemblyebene festzulegen.
Dies ist in Fällen erforderlich, in denen die Eigenschaft als retain
eigenschaft oder assign
nicht als copy
Eigenschaft deklariert Objective-C wird. Dies geschieht in der Regel in Drittanbieterbibliotheken, die von Entwicklern falsch "optimiert" wurden. Im Allgemeinen oder Eigenschaften sind falsch, retain
assign
NSString
da NSMutableString
oder vom Benutzer abgeleitete Klassen NSString
möglicherweise den Inhalt der Zeichenfolgen ändern können, ohne dass das Wissen über den Bibliothekscode bekannt ist, subtil die Anwendung zu unterbrechen. Dies geschieht in der Regel aufgrund vorzeitiger Optimierung.
Die folgende Abbildung zeigt zwei solche Eigenschaften in Objective-C:
@property(nonatomic,retain) NSString *name;
@property(nonatomic,assign) NSString *name2;
DisposeAttribute
Wenn Sie die [DisposeAttribute]
Klasse auf eine Klasse anwenden, geben Sie einen Codeausschnitt an, der der Dispose()
Methodenimplementierung der Klasse hinzugefügt wird.
Da die Dispose
Methode automatisch vom bgen
Tool generiert wird, müssen Sie das [Dispose]
Attribut verwenden, um Code in die generierte Dispose
Methodenimplementierung einzuordnen.
Zum Beispiel:
[BaseType (typeof (NSObject))]
[Dispose ("if (OpenConnections > 0) CloseAllConnections ();")]
interface DatabaseConnection {
}
ExportAttribute
Das [Export]
Attribut wird verwendet, um eine Methode oder Eigenschaft zu kennzeichnen, die für die Objective-C Laufzeit verfügbar gemacht werden soll. Dieses Attribut wird zwischen dem Bindungstool und der tatsächlichen Xamarin.iOS- und Xamarin.Mac-Laufzeit gemeinsam genutzt. Für Methoden wird der Parameter an den generierten Code übergeben, für Eigenschaften werden ein Getter- und Setter-Export basierend auf der Basisdeklaration generiert (informationen zum Ändern des Verhaltens des Bindungstools finden Sie im Abschnitt zu den [BindAttribute]
Informationen zum Ändern des Verhaltens des Bindungstools).
Syntax:
public enum ArgumentSemantic {
None, Assign, Copy, Retain.
}
[AttributeUsage (AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)]
public class ExportAttribute : Attribute {
public ExportAttribute();
public ExportAttribute (string selector);
public ExportAttribute (string selector, ArgumentSemantic semantic);
public string Selector { get; set; }
public ArgumentSemantic ArgumentSemantic { get; set; }
}
Die Auswahl stellt den Namen der zugrunde liegenden Objective-C Methode oder Eigenschaft dar, die gebunden wird.
ExportAttribute.ArgumentSemantic
FieldAttribute
Dieses Attribut wird verwendet, um eine globale C-Variable als Feld verfügbar zu machen, das bei Bedarf geladen und C#-Code verfügbar gemacht wird. In der Regel ist dies erforderlich, um die Werte von Konstanten abzurufen, die in C definiert sind oder Objective-C die entweder Token sein können, die in einigen APIs verwendet werden oder deren Werte undurchsichtig sind und wie vom Benutzercode verwendet werden müssen.
Syntax:
public class FieldAttribute : Attribute {
public FieldAttribute (string symbolName);
public FieldAttribute (string symbolName, string libraryName);
public string SymbolName { get; set; }
public string LibraryName { get; set; }
}
Dies symbolName
ist das C-Symbol, mit dem eine Verknüpfung hergestellt werden soll. Standardmäßig wird dies aus einer Bibliothek geladen, deren Name aus dem Namespace abgeleitet wird, in dem der Typ definiert ist. Wenn dies nicht die Bibliothek ist, in der das Symbol nachschlagen soll, sollten Sie den libraryName
Parameter übergeben. Wenn Sie eine statische Bibliothek verknüpfen, verwenden Sie __Internal
sie als libraryName
Parameter.
Die generierten Eigenschaften sind immer statisch.
Eigenschaften, die mit dem Field-Attribut gekennzeichnet sind, können die folgenden Typen aufweisen:
NSString
NSArray
nint
/int
/long
nuint
/uint
/ulong
nfloat
/float
double
CGSize
System.IntPtr
- Enumerationen
Setter werden für Enumerationen, die von NSString-Konstanten unterstützt werden, nicht unterstützt, können aber bei Bedarf manuell gebunden werden.
Beispiel:
[Static]
interface CameraEffects {
[Field ("kCameraEffectsZoomFactorKey", "CameraLibrary")]
NSString ZoomFactorKey { get; }
}
InternalAttribute
Das [Internal]
Attribut kann auf Methoden oder Eigenschaften angewendet werden und hat die Auswirkung, den generierten Code mit dem internal
C#-Schlüsselwort zu kennzeichnen, wodurch der Code nur für Code in der generierten Assembly zugänglich ist. Dies wird in der Regel verwendet, um APIs auszublenden, die zu niedrig sind oder eine suboptimale öffentliche API bereitstellen, die Sie verbessern möchten, oder für APIs, die vom Generator nicht unterstützt werden und einige Handcodierung erfordern.
Wenn Sie die Bindung entwerfen, blenden Sie die Methode oder Eigenschaft in der Regel mithilfe dieses Attributs aus und geben einen anderen Namen für die Methode oder Eigenschaft an, und dann fügen Sie in der ergänzenden C#-Unterstützungsdatei einen stark typierten Wrapper hinzu, der die zugrunde liegende Funktionalität verfügbar macht.
Zum Beispiel:
[Internal]
[Export ("setValue:forKey:")]
void _SetValueForKey (NSObject value, NSObject key);
[Internal]
[Export ("getValueForKey:")]
NSObject _GetValueForKey (NSObject key);
Dann könnten Sie in Ihrer Unterstützenden Datei code wie folgt haben:
public NSObject this [NSObject idx] {
get {
return _GetValueForKey (idx);
}
set {
_SetValueForKey (value, idx);
}
}
IsThreadStaticAttribute
Dieses Attribut kennzeichnet das Sicherungsfeld für eine Eigenschaft, die mit dem .NET-Attribut [ThreadStatic]
kommentiert werden soll. Dies ist nützlich, wenn das Feld eine statische Threadvariable ist.
MarshalNativeExceptions (Xamarin.iOS 6.0.6)
Dieses Attribut unterstützt systemeigene (Objective-C) Ausnahmen.
Anstatt direkt aufzurufen objc_msgSend
, durchläuft der Aufruf ein benutzerdefiniertes Trampolin, das ObjectiveC-Ausnahmen fängt und sie in verwaltete Ausnahmen marshallt.
Derzeit werden nur einige objc_msgSend
Signaturen unterstützt (Sie werden herausfinden, ob eine Signatur nicht unterstützt wird, wenn die systemeigene Verknüpfung einer App, die die Bindung verwendet, mit einem fehlenden xamarin__objc_msgSend-Symbol fehlschlägt), aber mehr kann auf Anforderung hinzugefügt werden.
NewAttribute
Dieses Attribut wird auf Methoden und Eigenschaften angewendet, damit der Generator das new
Schlüsselwort vor der Deklaration generiert.
Es wird verwendet, um Compilerwarnungen zu vermeiden, wenn derselbe Methoden- oder Eigenschaftenname in einer Unterklasse eingeführt wird, die bereits in einer Basisklasse vorhanden ist.
NotificationAttribute
Sie können dieses Attribut auf Felder anwenden, damit der Generator eine stark typierte Hilfsklasse Benachrichtigungen erzeugt.
Dieses Attribut kann ohne Argumente für Benachrichtigungen verwendet werden, die keine Nutzlast enthalten, oder Sie können ein Attribut angeben, das auf eine System.Type
andere Schnittstelle in der API-Definition verweist, in der Regel mit dem Namen, der mit "EventArgs" endet. Der Generator wandelt die Schnittstelle in eine Klasse um, die Unterklassen EventArgs
enthält und alle dort aufgeführten Eigenschaften enthält. Das [Export]
Attribut sollte in der EventArgs
Klasse verwendet werden, um den Namen des Schlüssels aufzulisten, der zum Nachschlagen des Objective-C Wörterbuchs zum Abrufen des Werts verwendet wird.
Zum Beispiel:
interface MyClass {
[Notification]
[Field ("MyClassDidStartNotification")]
NSString DidStartNotification { get; }
}
Der obige Code generiert eine geschachtelte Klasse MyClass.Notifications
mit den folgenden Methoden:
public class MyClass {
[..]
public Notifications {
public static NSObject ObserveDidStart (EventHandler<NSNotificationEventArgs> handler)
public static NSObject ObserveDidStart (NSObject objectToObserve, EventHandler<NSNotificationEventArgs> handler)
}
}
Benutzer Ihres Codes können dann ganz einfach Benachrichtigungen abonnieren, die im NSDefaultCenter gepostet wurden, indem Sie Code wie folgt verwenden:
var token = MyClass.Notifications.ObserverDidStart ((notification) => {
Console.WriteLine ("Observed the 'DidStart' event!");
});
Oder um ein bestimmtes Zu beobachtende Objekt festzulegen. Wenn Sie an objectToObserve
diese Methode übergeben null
werden, verhält sich genau wie der andere Peer.
var token = MyClass.Notifications.ObserverDidStart (objectToObserve, (notification) => {
Console.WriteLine ("Observed the 'DidStart' event on objectToObserve!");
});
Der zurückgegebene Wert ObserveDidStart
kann verwendet werden, um den Empfang von Benachrichtigungen wie folgt zu beenden:
token.Dispose ();
Oder Sie können NSNotification.DefaultCenter.RemoveObserver aufrufen und das Token übergeben. Wenn Ihre Benachrichtigung Parameter enthält, sollten Sie wie folgt eine Hilfsschnittstelle EventArgs
angeben:
interface MyClass {
[Notification (typeof (MyScreenChangedEventArgs)]
[Field ("MyClassScreenChangedNotification")]
NSString ScreenChangedNotification { get; }
}
// The helper EventArgs declaration
interface MyScreenChangedEventArgs {
[Export ("ScreenXKey")]
nint ScreenX { get; set; }
[Export ("ScreenYKey")]
nint ScreenY { get; set; }
[Export ("DidGoOffKey")]
[ProbePresence]
bool DidGoOff { get; }
}
Im obigen Beispiel wird eine MyScreenChangedEventArgs
Klasse mit den ScreenX
Und ScreenY
Eigenschaften generiert, mit denen die Daten aus dem NSNotification.UserInfo-Wörterbuch mithilfe der Schlüssel ScreenXKey
abgerufen werden, bzw ScreenYKey
. die richtigen Konvertierungen angewendet werden. Das [ProbePresence]
Attribut wird verwendet, um den Generator zu untersuchen, wenn der Schlüssel im UserInfo
Schlüssel festgelegt ist, anstatt zu versuchen, den Wert zu extrahieren. Dies wird für Fälle verwendet, in denen das Vorhandensein des Schlüssels der Wert ist (in der Regel für boolesche Werte).
Auf diese Weise können Sie Code wie folgt schreiben:
var token = MyClass.NotificationsObserveScreenChanged ((notification) => {
Console.WriteLine ("The new screen dimensions are {0},{1}", notification.ScreenX, notification.ScreenY);
});
In einigen Fällen ist keine Konstante mit dem wert verknüpft, der für das Wörterbuch übergeben wird. Apple verwendet manchmal öffentliche Symbolkonstanten und verwendet manchmal Zeichenfolgenkonstanten. Standardmäßig verwendet das [Export]
Attribut in Ihrer bereitgestellten EventArgs
Klasse den angegebenen Namen als öffentliches Symbol, um zur Laufzeit nachzuschlagen. Wenn dies nicht der Fall ist und stattdessen als Zeichenfolgenkonstante nachschlagen soll, übergeben Sie den ArgumentSemantic.Assign
Wert an das Export-Attribut.
Neu in Xamarin.iOS 8.4
Manchmal beginnen Benachrichtigungen ohne Argumente, sodass die Verwendung [Notification]
ohne Argumente akzeptabel ist. Manchmal werden jedoch Parameter für die Benachrichtigung eingeführt. Um dieses Szenario zu unterstützen, kann das Attribut mehrmals angewendet werden.
Wenn Sie eine Bindung entwickeln und vermeiden möchten, vorhandenen Benutzercode zu unterbrechen, würden Sie eine vorhandene Benachrichtigung von:
interface MyClass {
[Notification]
[Field ("MyClassScreenChangedNotification")]
NSString ScreenChangedNotification { get; }
}
In einer Version, die das Benachrichtigungsattribut zweimal auflistet, wie folgt:
interface MyClass {
[Notification]
[Notification (typeof (MyScreenChangedEventArgs)]
[Field ("MyClassScreenChangedNotification")]
NSString ScreenChangedNotification { get; }
}
NullAllowedAttribute
Wenn dies auf eine Eigenschaft angewendet wird, kennzeichnet sie die Eigenschaft so, dass dem Wert null
zugewiesen werden kann. Dies gilt nur für Referenztypen.
Wenn dies auf einen Parameter in einer Methodensignatur angewendet wird, gibt es an, dass der angegebene Parameter null sein kann und dass keine Überprüfung für das Übergeben null
von Werten ausgeführt werden soll.
Wenn der Verweistyp dieses Attribut nicht aufweist, generiert das Bindungstool eine Überprüfung auf den wert, der zugewiesen wird, bevor er an ihn Objective-C übergeben wird, und generiert eine Überprüfung, die ausgelöst ArgumentNullException
wird, wenn der zugewiesene Wert ist null
.
Zum Beispiel:
// In properties
[NullAllowed]
UIImage IconFile { get; set; }
// In methods
void SetImage ([NullAllowed] UIImage image, State forState);
OverrideAttribute
Verwenden Sie dieses Attribut, um den Bindungsgenerator anzuweisen, dass die Bindung für diese bestimmte Methode mit einem override
Schlüsselwort gekennzeichnet werden soll.
PreSnippetAttribute
Sie können dieses Attribut verwenden, um Code einzufügen, der eingefügt werden soll, nachdem die Eingabeparameter überprüft wurden, aber bevor der Code aufgerufen wird Objective-C.
Beispiel:
[Export ("demo")]
[PreSnippet ("var old = ViewController;")]
void Demo ();
PrologueSnippetAttribute
Sie können dieses Attribut verwenden, um Code einzufügen, der eingefügt werden soll, bevor eine der Parameter in der generierten Methode überprüft wird.
Beispiel:
[Export ("demo")]
[Prologue ("Trace.Entry ();")]
void Demo ();
PostGetAttribute
Weist den Bindungsgenerator an, die angegebene Eigenschaft aus dieser Klasse aufzurufen, um einen Wert daraus abzurufen.
Diese Eigenschaft wird in der Regel verwendet, um den Cache zu aktualisieren, der auf Objekte verweist, auf die das Objektdiagramm verweist. Normalerweise wird er im Code mit Vorgängen wie "Hinzufügen/Entfernen" angezeigt. Diese Methode wird verwendet, damit nach dem Hinzufügen oder Entfernen von Elementen der interne Cache aktualisiert wird, um sicherzustellen, dass verwaltete Verweise auf Objekte beibehalten werden, die tatsächlich verwendet werden. Dies ist möglich, da das Bindungstool ein Sicherungsfeld für alle Referenzobjekte in einer bestimmten Bindung generiert.
Beispiel:
[BaseType (typeof (NSObject))]
public interface NSOperation {
[Export ("addDependency:")][PostGet ("Dependencies")]
void AddDependency (NSOperation op);
[Export ("removeDependency:")][PostGet ("Dependencies")]
void RemoveDependency (NSOperation op);
[Export ("dependencies")]
NSOperation [] Dependencies { get; }
}
In diesem Fall wird die Dependencies
Eigenschaft nach dem Hinzufügen oder Entfernen von Abhängigkeiten aus dem NSOperation
Objekt aufgerufen, um sicherzustellen, dass wir über ein Diagramm verfügen, das die tatsächlich geladenen Objekte darstellt, wodurch sowohl Speicherverluste als auch Speicherbeschädigungen verhindert werden.
PostSnippetAttribute
Sie können dieses Attribut verwenden, um einen C#-Quellcode einzufügen, der eingefügt werden soll, nachdem der Code die zugrunde liegende Objective-C Methode aufgerufen hat.
Beispiel:
[Export ("demo")]
[PostSnippet ("if (old != null) old.DemoComplete ();")]
void Demo ();
ProxyAttribute
Dieses Attribut wird angewendet, um Werte zurückzugeben, um sie als Proxyobjekte zu kennzeichnen. Einige Objective-C APIs geben Proxyobjekte zurück, die nicht von Benutzerbindungen unterschieden werden können. Die Auswirkung dieses Attributs besteht darin, das Objekt als Objekt zu DirectBinding
kennzeichnen. Für ein Szenario in Xamarin.Mac können Sie die Diskussion zu diesem Fehler sehen.
ReleaseAttribute (Xamarin.iOS 6.0)
Dies kann auf Rückgabetypen angewendet werden, um anzugeben, dass der Generator das Objekt aufrufen Release
soll, bevor es zurückgegeben wird. Dies ist nur erforderlich, wenn Ihnen eine Methode ein beibehaltenes Objekt (im Gegensatz zu einem autoreleased-Objekt, das am häufigsten verwendet wird) zur Verfügung stellt.
Beispiel:
[Export ("getAndRetainObject")]
[return: Release ()]
NSObject GetAndRetainObject ();
Darüber hinaus wird dieses Attribut an den generierten Code weitergegeben, damit die Xamarin.iOS-Laufzeit weiß, dass es das Objekt beibehalten muss, wenn es von einer solchen Funktion zurückgegeben Objective-C wird.
SealedAttribute
Weist den Generator an, die generierte Methode als versiegelt zu kennzeichnen. Wenn dieses Attribut nicht angegeben ist, wird standardmäßig eine virtuelle Methode generiert (entweder eine virtuelle Methode, eine abstrakte Methode oder eine Außerkraftsetzung, je nachdem, wie andere Attribute verwendet werden).
StaticAttribute
Wenn das [Static]
Attribut auf eine Methode oder Eigenschaft angewendet wird, generiert dies eine statische Methode oder Eigenschaft. Wenn dieses Attribut nicht angegeben ist, erzeugt der Generator eine Instanzmethode oder -eigenschaft.
TransientAttribute
Verwenden Sie dieses Attribut, um Eigenschaften zu kennzeichnen, deren Werte vorübergehend sind, d. h. Objekte, die vorübergehend von iOS erstellt werden, aber nicht langlebig sind. Wenn dieses Attribut auf eine Eigenschaft angewendet wird, erstellt der Generator kein Sicherungsfeld für diese Eigenschaft, was bedeutet, dass die verwaltete Klasse keinen Verweis auf das Objekt behält.
WrapAttribute
Im Design der Xamarin.iOS/Xamarin.Mac-Bindungen wird das [Wrap]
Attribut verwendet, um ein schwach typiertes Objekt mit einem stark typierten Objekt umzuschließen. Dies wird hauptsächlich mit Objective-C Delegatobjekten gespielt, die in der Regel als Typ id
deklariert werden oder NSObject
. Die Konvention, die von Xamarin.iOS und Xamarin.Mac verwendet wird, besteht darin, diese Delegaten oder Datenquellen als Typ NSObject
verfügbar zu machen und mit der Konvention "Weak" + dem verfügbar gemachten Namen benannt zu werden. Eine id delegate
Eigenschaft aus Objective-C dieser Eigenschaft würde als NSObject WeakDelegate { get; set; }
Eigenschaft in der API-Vertragsdatei verfügbar gemacht werden.
Der Wert, der dieser Stellvertretung zugewiesen ist, weist jedoch in der Regel einen starken Typ auf, sodass wir den starken Typ darstellen und das [Wrap]
Attribut anwenden. Dies bedeutet, dass Benutzer schwache Typen verwenden können, wenn sie eine feine Kontrolle benötigen oder wenn sie auf Tricks mit niedriger Ebene zurückgreifen müssen, oder sie können die stark typierte Eigenschaft für die meisten ihrer Arbeit verwenden.
Beispiel:
[BaseType (typeof (NSObject))]
interface Demo {
[Export ("delegate"), NullAllowed]
NSObject WeakDelegate { get; set; }
[Wrap ("WeakDelegate")]
DemoDelegate Delegate { get; set; }
}
[BaseType (typeof (NSObject))]
[Model][Protocol]
interface DemoDelegate {
[Export ("doDemo")]
void DoDemo ();
}
So würde der Benutzer die schwach typierte Version der Stellvertretung verwenden:
// The weak case, user has to roll his own
class SomeObject : NSObject {
[Export ("doDemo")]
void CallbackForDoDemo () {}
}
var demo = new Demo ();
demo.WeakDelegate = new SomeObject ();
Und dies ist, wie der Benutzer die stark typierte Version verwenden würde, beachten Sie, dass der Benutzer das C#-Typsystem nutzt und das Überschreibungsschlüsselwort verwendet, um seine Absicht zu deklarieren und die Methode [Export]
nicht manuell zu dekorieren, da wir dies in der Bindung für den Benutzer getan haben:
// This is the strong case,
class MyDelegate : DemoDelegate {
override void Demo DoDemo () {}
}
var strongDemo = new Demo ();
demo.Delegate = new MyDelegate ();
Eine weitere Verwendung des [Wrap]
Attributs besteht darin, stark typierte Versionen von Methoden zu unterstützen. Zum Beispiel:
[BaseType (typeof (NSObject))]
interface XyzPanel {
[Export ("playback:withOptions:")]
void Playback (string fileName, [NullAllowed] NSDictionary options);
[Wrap ("Playback (fileName, options?.Dictionary")]
void Playback (string fileName, XyzOptions options);
}
Wenn das [Wrap]
Attribut auf eine Methode innerhalb eines Typs angewendet wird, der mit einem [Category]
Attribut versehen ist, müssen Sie als erstes Argument einschließen This
, da eine Erweiterungsmethode generiert wird. Zum Beispiel:
[Wrap ("Write (This, image, options?.Dictionary, out error)")]
bool Write (CIImage image, CIImageRepresentationOptions options, out NSError error);
Die von [Wrap]
ihnen generierten Member sind nicht virtual
standardmäßig vorhanden, wenn Sie ein virtual
Element benötigen, das Sie auf true
den optionalen isVirtual
Parameter festlegen können.
[BaseType (typeof (NSObject))]
interface FooExplorer {
[Export ("fooWithContentsOfURL:")]
void FromUrl (NSUrl url);
[Wrap ("FromUrl (NSUrl.FromString (url))", isVirtual: true)]
void FromUrl (string url);
}
[Wrap]
kann auch direkt in Eigenschaften-Getters und Settern verwendet werden.
Auf diese Weise können Sie die volle Kontrolle darüber haben und den Code nach Bedarf anpassen.
Betrachten Sie beispielsweise die folgende API-Definition, die intelligente Enumerationen verwendet:
// Smart enum.
enum PersonRelationship {
[Field (null)]
None,
[Field ("FMFather", "__Internal")]
Father,
[Field ("FMMother", "__Internal")]
Mother
}
Schnittstellendefinition:
// Property definition.
[Export ("presenceType")]
NSString _PresenceType { get; set; }
PersonRelationship PresenceType {
[Wrap ("PersonRelationshipExtensions.GetValue (_PresenceType)")]
get;
[Wrap ("_PresenceType = value.GetConstant ()")]
set;
}
Parameterattribute
In diesem Abschnitt werden die Attribute beschrieben, die Sie auf die Parameter in einer Methodendefinition anwenden können, sowie die Attribute, die [NullAttribute]
für eine Eigenschaft als Ganzes gelten.
BlockCallback
Dieses Attribut wird auf Parametertypen in C#-Delegatdeklarationen angewendet, um den betreffenden Ordner zu benachrichtigen, dass der betreffende Parameter der Objective-C Blockaufrufkonvention entspricht und auf diese Weise marshallen sollte.
Dies wird in der Regel für Rückrufe verwendet, die wie folgt definiert sind:Objective-C
typedef returnType (^SomeTypeDefinition) (int parameter1, NSString *parameter2);
Siehe auch: CCallback.
CCallback
Dieses Attribut wird auf Parametertypen in C#-Delegatdeklarationen angewendet, um den betreffenden Ordner zu benachrichtigen, dass der betreffende Parameter der C ABI-Funktionszeigeraufrufkonvention entspricht und auf diese Weise marshallen sollte.
Dies wird in der Regel für Rückrufe verwendet, die wie folgt definiert sind:Objective-C
typedef returnType (*SomeTypeDefinition) (int parameter1, NSString *parameter2);
Siehe auch: BlockCallback.
Parameter
Sie können das [Params]
Attribut für den letzten Arrayparameter einer Methodendefinition verwenden, damit der Generator eine "Params" in die Definition einfüge. Auf diese Weise kann die Bindung auf einfache Weise optionale Parameter zulassen.
Beispielsweise die folgende Definition:
[Export ("loadFiles:")]
void LoadFiles ([Params]NSUrl [] files);
Ermöglicht das Schreiben des folgenden Codes:
foo.LoadFiles (new NSUrl (url));
foo.LoadFiles (new NSUrl (url1), new NSUrl (url2), new NSUrl (url3));
Dies hat den zusätzlichen Vorteil, dass Benutzer kein Array rein zum Übergeben von Elementen erstellen müssen.
PlainString
Sie können das [PlainString]
Attribut vor Zeichenfolgenparametern verwenden, um den Bindungsgenerator anzuweisen, die Zeichenfolge als C-Zeichenfolge zu übergeben, anstatt den Parameter als ein NSString
.
Die meisten Objective-C APIs verbrauchen NSString
Parameter, aber eine Handvoll APIs machen eine char *
API zum Übergeben von Zeichenfolgen anstelle der NSString
Variation verfügbar.
Wird in diesen Fällen verwendet [PlainString]
.
Beispielsweise die folgenden Objective-C Deklarationen:
- (void) setText: (NSString *) theText;
- (void) logMessage: (char *) message;
Sollte wie folgt gebunden sein:
[Export ("setText:")]
void SetText (string theText);
[Export ("logMessage:")]
void LogMessage ([PlainString] string theText);
RetainAttribute
Weist den Generator an, einen Verweis auf den angegebenen Parameter beizubehalten. Der Generator stellt den Sicherungsspeicher für dieses Feld bereit, oder Sie können einen Namen (das WrapName
) angeben, unter dem der Wert gespeichert werden soll. Dies ist nützlich, um einen Verweis auf ein verwaltetes Objekt zu speichern, das als Parameter Objective-C übergeben wird, und wenn Sie wissen, dass Objective-C diese Kopie des Objekts nur beibehalten wird. Beispielsweise würde eine API SetDisplay (SomeObject)
dieses Attribut verwenden, da es wahrscheinlich ist, dass das SetDisplay nur jeweils ein Objekt anzeigen konnte. Wenn Sie mehrere Objekte (z. B. für eine Stack-like-API) nachverfolgen müssen, verwenden Sie das [RetainList]
Attribut.
Syntax:
public class RetainAttribute {
public RetainAttribute ();
public RetainAttribute (string wrapName);
public string WrapName { get; }
}
TransientAttribute
Dieses Attribut wird auf Parameter angewendet und nur beim Übergang von Objective-C C# verwendet. Während dieser Übergänge werden die verschiedenen Objective-CNSObject
Parameter in eine verwaltete Darstellung des Objekts eingeschlossen.
Die Laufzeit verwendet einen Verweis auf das systemeigene Objekt und behält den Verweis bei, bis der letzte verwaltete Verweis auf das Objekt nicht mehr vorhanden ist, und die GC hat die Möglichkeit, ausgeführt zu werden.
In einigen Fällen ist es für die C#-Laufzeit wichtig, keinen Verweis auf das systemeigene Objekt beizubehalten. Dies geschieht manchmal, wenn der zugrunde liegende systemeigene Code ein spezielles Verhalten an den Lebenszyklus des Parameters angefügt hat. Beispiel: Der Destruktor für den Parameter führt eine Bereinigungsaktion aus, oder entfernt einige wertvolle Ressourcen.
Dieses Attribut informiert die Laufzeit, dass das Objekt ggf. verworfen werden soll, wenn es von der überschriebenen Methode zurückgegeben Objective-C wird.
Die Regel ist einfach: Wenn die Laufzeit eine neue verwaltete Darstellung aus dem systemeigenen Objekt erstellen musste, wird am Ende der Funktion die Aufbewahrungsanzahl für das systemeigene Objekt gelöscht, und die Handle-Eigenschaft des verwalteten Objekts wird gelöscht. Dies bedeutet, dass wenn Sie einen Verweis auf das verwaltete Objekt beibehalten, dieser Verweis nutzlos wird (das Aufrufen von Methoden darauf löst eine Ausnahme aus).
Wenn das übergebene Objekt nicht erstellt wurde oder bereits eine ausstehende verwaltete Darstellung des Objekts vorhanden ist, wird das erzwungene Dispose nicht ausgeführt.
Eigenschaftsattribute
NotImplementedAttribute
Dieses Attribut wird verwendet, um einen Objective-C Idiom zu unterstützen, bei dem eine Eigenschaft mit einem Getter in einer Basisklasse eingeführt wird, und eine veränderbare Unterklasse führt einen Setter ein.
Da C# dieses Modell nicht unterstützt, muss die Basisklasse sowohl den Setter als auch den Getter aufweisen, und eine Unterklasse kann das OverrideAttribute verwenden.
Dieses Attribut wird nur in Eigenschaftensatzern verwendet und wird verwendet, um das veränderbare Idiom in Objective-Czu unterstützen.
Beispiel:
[BaseType (typeof (NSObject))]
interface MyString {
[Export ("initWithValue:")]
IntPtr Constructor (string value);
[Export ("value")]
string Value {
get;
[NotImplemented ("Not available on MyString, use MyMutableString to set")]
set;
}
}
[BaseType (typeof (MyString))]
interface MyMutableString {
[Export ("value")]
[Override]
string Value { get; set; }
}
Enumerationsattribute
Das Zuordnen von NSString
Konstanten zu Enumerationswerten ist eine einfache Möglichkeit zum Erstellen einer besseren .NET-API. Sie hat folgende Aufgaben:
- ermöglicht es, dass der Code abgeschlossen werden kann, indem nur die richtigen Werte für die API angezeigt werden;
- fügt Die Typsicherheit hinzu, Sie können keine andere
NSString
Konstante in einem falschen Kontext verwenden; - ermöglicht das Ausblenden einiger Konstanten, wodurch der Codeabschluss kürzere API-Liste ohne Funktionsverlust zeigt.
Beispiel:
enum NSRunLoopMode {
[DefaultEnumValue]
[Field ("NSDefaultRunLoopMode")]
Default,
[Field ("NSRunLoopCommonModes")]
Common,
[Field (null)]
Other = 1000
}
Aus der obigen Bindungsdefinition erstellt der Generator den enum
selbst und erstellt auch einen *Extensions
statischen Typ, der zwei Wege Konvertierungsmethoden zwischen den Enumerationswerten und den NSString
Konstanten enthält. Dies bedeutet, dass die Konstanten entwicklern weiterhin zur Verfügung stehen, auch wenn sie nicht Teil der API sind.
Beispiele:
// using the NSString constant in a different API / framework / 3rd party code
CallApiRequiringAnNSString (NSRunLoopMode.Default.GetConstant ());
// converting the constants from a different API / framework / 3rd party code
var constant = CallApiReturningAnNSString ();
// back into an enum value
CallApiWithEnum (NSRunLoopModeExtensions.GetValue (constant));
DefaultEnumValueAttribute
Sie können einen Enumerationswert mit diesem Attribut versehen. Dies wird zu der Konstante, die zurückgegeben wird, wenn der Enumerationswert nicht bekannt ist.
Aus dem obigen Beispiel:
var x = (NSRunLoopMode) 99;
Call (x.GetConstant ()); // NSDefaultRunLoopMode will be used
Wenn kein Enumerationswert eingerichtet ist, wird ein NotSupportedException
Wurf ausgelöst.
ErrorDomainAttribute
Fehlercodes sind als Enumerationswerte gebunden. Es gibt in der Regel eine Fehlerdomäne für sie, und es ist nicht immer leicht zu finden, welches gilt (oder wenn eine sogar vorhanden ist).
Sie können dieses Attribut verwenden, um die Fehlerdomäne der Enumeration selbst zuzuordnen.
Beispiel:
[Native]
[ErrorDomain ("AVKitErrorDomain")]
public enum AVKitError : nint {
None = 0,
Unknown = -1000,
PictureInPictureStartFailed = -1001
}
Anschließend können Sie die Erweiterungsmethode GetDomain
aufrufen, um die Domänenkonstante eines beliebigen Fehlers abzurufen.
FieldAttribute
Dies ist dasselbe [Field]
Attribut, das für Konstanten innerhalb des Typs verwendet wird. Sie kann auch in Enumerationen verwendet werden, um einen Wert mit einer bestimmten Konstante zuzuordnen.
Ein null
Wert kann verwendet werden, um anzugeben, welcher Enumerationswert zurückgegeben werden soll, wenn eine null
NSString
Konstante angegeben wird.
Aus dem obigen Beispiel:
var constant = NSRunLoopMode.NewInWatchOS3; // will be null in watchOS 2.x
Call (NSRunLoopModeExtensions.GetValue (constant)); // will return 1000
Wenn kein null
Wert vorhanden ist, wird ein ArgumentNullException
Fehler ausgelöst.
Globale Attribute
Globale Attribute werden entweder mit dem Attributmodifizierer wie dem [assembly:]
[LinkWithAttribute]
oder überall angewendet, z. B. den Verfügbarkeitsattributen.
LinkWithAttribute
Dies ist ein Attribut auf Assemblyebene, mit dem Entwickler die Verknüpfungskennzeichnungen angeben können, die zum Wiederverwenden einer gebundenen Bibliothek erforderlich sind, ohne dass der Consumer der Bibliothek gezwungen wird, die an eine Bibliothek übergebenen gcc_flags und zusätzliche mtouch-Argumente manuell zu konfigurieren.
Syntax:
// In properties
[Flags]
public enum LinkTarget {
Simulator = 1,
ArmV6 = 2,
ArmV7 = 4,
Thumb = 8,
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple=true)]
public class LinkWithAttribute : Attribute {
public LinkWithAttribute ();
public LinkWithAttribute (string libraryName);
public LinkWithAttribute (string libraryName, LinkTarget target);
public LinkWithAttribute (string libraryName, LinkTarget target, string linkerFlags);
public bool ForceLoad { get; set; }
public string Frameworks { get; set; }
public bool IsCxx { get; set; }
public string LibraryName { get; }
public string LinkerFlags { get; set; }
public LinkTarget LinkTarget { get; set; }
public bool NeedsGccExceptionHandling { get; set; }
public bool SmartLink { get; set; }
public string WeakFrameworks { get; set; }
}
Dieses Attribut wird beispielsweise auf Assemblyebene angewendet, was die CorePlot-Bindungen verwenden:
[assembly: LinkWith ("libCorePlot-CocoaTouch.a", LinkTarget.ArmV7 | LinkTarget.ArmV7s | LinkTarget.Simulator, Frameworks = "CoreGraphics QuartzCore", ForceLoad = true)]
Wenn Sie das [LinkWith]
Attribut verwenden, wird die angegebene libraryName
in die resultierende Assembly eingebettet, sodass Benutzer eine einzelne DLL versenden können, die sowohl die nicht verwalteten Abhängigkeiten als auch die Befehlszeilenkennzeichnungen enthält, die erforderlich sind, um die Bibliothek von Xamarin.iOS ordnungsgemäß zu nutzen.
Es ist auch möglich, kein Attribut anzugeben libraryName
, in diesem Fall kann das LinkWith
Attribut verwendet werden, um nur zusätzliche Linkerkennzeichnungen anzugeben:
[assembly: LinkWith (LinkerFlags = "-lsqlite3")]
LinkWithAttribute-Konstruktoren
Mit diesen Konstruktoren können Sie die Bibliothek angeben, mit der eine Verknüpfung hergestellt und in die resultierende Assembly eingebettet werden soll, die unterstützten Ziele, die von der Bibliothek unterstützt werden, und alle optionalen Bibliothekskennzeichnungen, die für die Verknüpfung mit der Bibliothek erforderlich sind.
Beachten Sie, dass das LinkTarget
Argument von Xamarin.iOS abgeleitet wird und nicht festgelegt werden muss.
Beispiele:
// Specify additional linker:
[assembly: LinkWith (LinkerFlags = "-sqlite3")]
// Specify library name for the constructor:
[assembly: LinkWith ("libDemo.a");
// Specify library name, and link target for the constructor:
[assembly: LinkWith ("libDemo.a", LinkTarget.Thumb | LinkTarget.Simulator);
// Specify only the library name, link target and linker flags for the constructor:
[assembly: LinkWith ("libDemo.a", LinkTarget.Thumb | LinkTarget.Simulator, SmartLink = true, ForceLoad = true, IsCxx = true);
LinkWithAttribute.ForceLoad
Die ForceLoad
Eigenschaft wird verwendet, um zu entscheiden, ob das Verknüpfungsflaggen -force_load
zum Verknüpfen der systemeigenen Bibliothek verwendet wird. Für den Heutigen sollte dies immer wahr sein.
LinkWithAttribute.Frameworks
Wenn die gebundene Bibliothek für alle Frameworks (außer Foundation
und UIKit
) eine harte Anforderung hat, sollten Sie die Eigenschaft auf eine Zeichenfolge festlegen, die Frameworks
eine durch Leerzeichen getrennte Liste der erforderlichen Plattformframeworks enthält. Wenn Sie z. B. eine Bibliothek binden, die erforderlich ist CoreGraphics
und CoreText
, legen Sie die Frameworks
Eigenschaft auf "CoreGraphics CoreText"
.
LinkWithAttribute.IsCxx
Legen Sie diese Eigenschaft auf "true" fest, wenn die resultierende ausführbare Datei mithilfe eines C++-Compilers anstelle des Standardwerts kompiliert werden muss, bei dem es sich um einen C-Compiler handelt. Verwenden Sie dies, wenn die Bibliothek, die Sie binden, in C++ geschrieben wurde.
LinkWithAttribute.LibraryName
Der Name der nicht verwalteten Bibliothek, die gebündelt werden soll. Dies ist eine Datei mit der Erweiterung ".a" und kann Objektcode für mehrere Plattformen enthalten (z. B. ARM und x86 für den Simulator).
In früheren Versionen von Xamarin.iOS wurde die LinkTarget
Eigenschaft überprüft, um die von Ihrer Bibliothek unterstützte Plattform zu ermitteln, dies wird jedoch jetzt automatisch erkannt, und die LinkTarget
Eigenschaft wird ignoriert.
LinkWithAttribute.LinkerFlags
Die LinkerFlags
Zeichenfolge bietet eine Möglichkeit zum Binden von Autoren, um alle zusätzlichen Linkerkennzeichnungen anzugeben, die beim Verknüpfen der systemeigenen Bibliothek mit der Anwendung erforderlich sind.
Wenn die systemeigene Bibliothek beispielsweise libxml2 und zlib erfordert, legen Sie die LinkerFlags
Zeichenfolge auf "-lxml2 -lz"
.
LinkWithAttribute.LinkTarget
In früheren Versionen von Xamarin.iOS wurde die LinkTarget
Eigenschaft überprüft, um die von Ihrer Bibliothek unterstützte Plattform zu ermitteln, dies wird jedoch jetzt automatisch erkannt, und die LinkTarget
Eigenschaft wird ignoriert.
LinkWithAttribute.NeedsGccExceptionHandling
Legen Sie diese Eigenschaft auf "true" fest, wenn für die Bibliothek, die Sie verknüpfen, die GCC-Ausnahmebehandlungsbibliothek (gcc_eh) erforderlich ist.
LinkWithAttribute.SmartLink
Die SmartLink
Eigenschaft sollte auf "true" festgelegt werden, damit Xamarin.iOS bestimmen kann, ob ForceLoad
erforderlich ist oder nicht.
LinkWithAttribute.WeakFrameworks
Die WeakFrameworks
Eigenschaft funktioniert auf die gleiche Weise wie die Frameworks
Eigenschaft, mit der Ausnahme, dass zur Verknüpfungszeit der -weak_framework
Bezeichner für jedes der aufgelisteten Frameworks an gcc übergeben wird.
WeakFrameworks
ermöglicht es Bibliotheken und Anwendungen, sich schwach mit Plattformframeworks zu verknüpfen, damit sie sie optional verwenden können, wenn sie verfügbar sind, aber keine harte Abhängigkeit davon nehmen, was nützlich ist, wenn Ihre Bibliothek zusätzliche Features zu neueren Versionen von iOS hinzufügen soll. Weitere Informationen zu schwachen Verknüpfungen finden Sie in der Apple-Dokumentation zu schwachen Verknüpfungen.
Gute Kandidaten für schwache Verknüpfungen sind Frameworks
wie Konten, CoreBluetooth
, , CoreImage
, GLKit
und Twitter
NewsstandKit
da sie nur in iOS 5 verfügbar sind.
AdviceAttribute
Verwenden Sie dieses Attribut, um Entwicklern einen Hinweis auf andere APIs zu geben, die für sie möglicherweise bequemer sind. Wenn Sie beispielsweise eine stark typierte Version einer API bereitstellen, können Sie dieses Attribut für das schwach typierte Attribut verwenden, um den Entwickler zur besseren API zu leiten.
Die Informationen aus diesem Attribut werden in der Dokumentation und den Tools entwickelt, um Benutzern Vorschläge zur Verbesserung zu geben
RequiresSuperAttribute
Dies ist eine spezielle Unterklasse des [Advice]
Attributs, die zum Hinweis auf den Entwickler verwendet werden kann, für den ein Überschreiben einer Methode einen Aufruf der Basismethode (Overridden) erfordert .
Dies clang
entspricht __attribute__((objc_requires_super))
ZeroCopyStringsAttribute
Nur verfügbar in Xamarin.iOS 5.4 und höher.
Dieses Attribut weist den Generator an, dass die Bindung für diese spezifische Bibliothek (sofern angewendet mit [assembly:]
) oder der Typ die schnelle Nullkopie-Zeichenfolgenmarsing verwenden soll. Dieses Attribut entspricht dem Übergeben der Befehlszeilenoption --zero-copy
an den Generator.
Bei Verwendung von Nullkopien für Zeichenfolgen verwendet der Generator effektiv dieselbe C#-Zeichenfolge wie die Zeichenfolge, die verwendet wird, Objective-C ohne dass ein neues NSString
Objekt erstellt wird und das Kopieren der Daten aus den C#-Zeichenfolgen in die Objective-C Zeichenfolge vermieden wird. Der einzige Nachteil der Verwendung von Zero Copy-Zeichenfolgen besteht darin, dass Sie sicherstellen müssen, dass alle Zeichenfolgeneigenschaften, die umbrochen werden, als retain
gekennzeichnet werden oder copy
über den [DisableZeroCopy]
Attributsatz verfügen. Dies ist erforderlich, da das Handle für Zeichenfolgen mit Nullkopien auf dem Stapel zugewiesen wird und bei der Rückgabe der Funktion ungültig ist.
Beispiel:
[ZeroCopyStrings]
[BaseType (typeof (NSObject))]
interface MyBinding {
[Export ("name")]
string Name { get; set; }
[Export ("domain"), NullAllowed]
string Domain { get; set; }
[DisablZeroCopy]
[Export ("someRetainedNSString")]
string RetainedProperty { get; set; }
}
Sie können das Attribut auch auf Assemblyebene anwenden, und es gilt für alle Typen der Assembly:
[assembly:ZeroCopyStrings]
Stark typierte Wörterbücher
Mit Xamarin.iOS 8.0 wurde Unterstützung für die einfache Erstellung stark typierter Klassen eingeführt, die umschlossen werden NSDictionaries
.
Obwohl es immer möglich war, den DictionaryContainer-Datentyp zusammen mit einer manuellen API zu verwenden, ist es jetzt viel einfacher, dies zu tun. Weitere Informationen finden Sie unter "Surfacing Strong Types".
StrongDictionary
Wenn dieses Attribut auf eine Schnittstelle angewendet wird, erzeugt der Generator eine Klasse mit demselben Namen wie die Schnittstelle, die von DictionaryContainer abgeleitet wird, und wandelt jede in der Schnittstelle definierte Eigenschaft in einen stark typierten Getter und Setter für das Wörterbuch um.
Dadurch wird automatisch eine Klasse generiert, die aus einer vorhandenen NSDictionary
instanziierten oder neu erstellten Klasse instanziiert werden kann.
Dieses Attribut verwendet einen Parameter, den Namen der Klasse mit den Schlüsseln, die für den Zugriff auf die Elemente im Wörterbuch verwendet werden. Standardmäßig sucht jede Eigenschaft in der Schnittstelle mit dem Attribut nach einem Element im angegebenen Typ nach einem Namen mit dem Suffix "Key".
Zum Beispiel:
[StrongDictionary ("MyOptionKeys")]
interface MyOption {
string Name { get; set; }
nint Age { get; set; }
}
[Static]
interface MyOptionKeys {
// In Objective-C this is "NSString *MYOptionNameKey;"
[Field ("MYOptionNameKey")]
NSString NameKey { get; }
// In Objective-C this is "NSString *MYOptionAgeKey;"
[Field ("MYOptionAgeKey")]
NSString AgeKey { get; }
}
Im obigen Fall erzeugt die MyOption
Klasse eine Zeichenfolgeneigenschaft, für Name
die der MyOptionKeys.NameKey
Schlüssel im Wörterbuch verwendet wird, um eine Zeichenfolge abzurufen. Und verwendet den MyOptionKeys.AgeKey
Schlüssel für das Wörterbuch, um ein NSNumber
Int abzurufen.
Wenn Sie einen anderen Schlüssel verwenden möchten, können Sie beispielsweise das Export-Attribut für die Eigenschaft verwenden:
[StrongDictionary ("MyColoringKeys")]
interface MyColoringOptions {
[Export ("TheName")] // Override the default which would be NameKey
string Name { get; set; }
[Export ("TheAge")] // Override the default which would be AgeKey
nint Age { get; set; }
}
[Static]
interface MyColoringKeys {
// In Objective-C this is "NSString *MYColoringNameKey"
[Field ("MYColoringNameKey")]
NSString TheName { get; }
// In Objective-C this is "NSString *MYColoringAgeKey"
[Field ("MYColoringAgeKey")]
NSString TheAge { get; }
}
Starke Wörterbuchtypen
Die folgenden Datentypen werden in der StrongDictionary
Definition unterstützt:
C#-Schnittstellentyp | NSDictionary Speichertypus |
---|---|
bool |
Boolean in einem NSNumber |
Enumerationswerte | Ganze Zahl, die in einer NSNumber |
int |
32-Bit-Ganzzahl, die in einer NSNumber |
uint |
32-Bit-Ganzzahl ohne Vorzeichen, die in einer NSNumber |
nint |
NSInteger in einem NSNumber |
nuint |
NSUInteger in einem NSNumber |
long |
64-Bit-Ganzzahl, die in einer NSNumber |
float |
32-Bit-Ganzzahl, die als eine NSNumber |
double |
64-Bit-Ganzzahl, die als eine NSNumber |
NSObject und Unterklassen |
NSObject |
NSDictionary |
NSDictionary |
string |
NSString |
NSString |
NSString |
C# Array von NSObject |
NSArray |
C# Array von Enumerationen |
NSArray enthaltende NSNumber Werte |