Ereignisse, Protokolle und Delegaten in xamarin. IOSEvents, Protocols and Delegates in Xamarin.iOS

Xamarin. IOS verwendet Steuerelemente, um Ereignisse für die meisten Benutzerinteraktionen verfügbar zu machen.Xamarin.iOS uses controls to expose events for most user interactions. Xamarin. IOS-Anwendungen nutzen diese Ereignisse ähnlich wie herkömmliche .NET-Anwendungen.Xamarin.iOS applications consume these events in much the same way as do traditional .NET applications. Die xamarin. IOS-UIButton-Klasse verfügt beispielsweise über ein Ereignis namens touchupinside und nutzt dieses Ereignis genau so, als ob diese Klasse und dieses Ereignis in einer .net-App wären.For example, the Xamarin.iOS UIButton class has an event called TouchUpInside and consumes this event just as if this class and event were in a .NET app.

Neben diesem .net-Ansatz stellt xamarin. IOS ein anderes Modell zur Verfügung, das für komplexere Interaktionen und Daten Bindungen verwendet werden kann.Besides this .NET approach, Xamarin.iOS exposes another model that can be used for more complex interaction and data binding. Diese Methodik verwendet, was Apple zum Aufrufen von Delegaten und Protokollen aufruft.This methodology uses what Apple calls delegates and protocols. Delegaten sind in c# vergleichbar mit Delegaten, aber anstelle einer einzelnen Methode ist ein Delegat in Ziel-C eine ganze Klasse, die einem Protokoll entspricht.Delegates are similar in concept to delegates in C#, but instead of defining and calling a single method, a delegate in Objective-C is an entire class that conforms to a protocol. Ein Protokoll ähnelt einer Schnittstelle in c#, mit dem Unterschied, dass seine Methoden optional sein können.A protocol is similar to an interface in C#, except that its methods can be optional. Um z. b. eine uitableview mit Daten aufzufüllen, würden Sie eine Delegatklasse erstellen, die die im uitableviewdatasource-Protokoll definierten Methoden implementiert, die von der uitableview aufgerufen werden, um sich selbst aufzufüllen.So for example, to populate a UITableView with data, you would create a delegate class that implements the methods defined in the UITableViewDataSource protocol that the UITableView would call to populate itself.

In diesem Artikel erhalten Sie Informationen zu all diesen Themen, in denen Sie eine solide Grundlage für die Behandlung von Rückruf Szenarien in xamarin. IOS erhalten, einschließlich:In this article you’ll learn about all these topics, giving you a solid foundation for handling callback scenarios in Xamarin.iOS, including:

  • Ereignisse – Verwenden von .NET-Ereignissen mit UIKit-Steuerelementen.Events – Using .NET events with UIKit controls.
  • Protokolle – lernen Sie, welche Protokolle und wie Sie verwendet werden, und erstellen Sie ein Beispiel, das Daten für eine Karten Anmerkung bereitstellt.Protocols – Learning what protocols are and how they are used, and creating an example that provides data for a map annotation.
  • Delegaten – lernen über Ziel-C-Delegaten, indem Sie das Map-Beispiel erweitern, um die Benutzerinteraktion zu verarbeiten, die eine Anmerkung enthält, und dann den Unterschied zwischen starken und schwachen Delegaten zu erlernen und zu verwenden.Delegates – Learning about Objective-C delegates by extending the map example to handle user interaction that includes an annotation, then learning the difference between strong and weak delegates and when to use each of these.

Um Protokolle und Delegaten zu veranschaulichen, erstellen wir eine einfache Kartenanwendung, die eine Anmerkung zu einer Karte hinzufügt, wie hier gezeigt:To illustrate protocols and delegates, we’ll build a simple map application that adds an annotation to a map as shown here:

 Ein Beispiel für eine einfache Kartenanwendung, dieeiner Zuordnung eine Anmerkung hinzufügt,  eine einer Karte hinzugefügte Beispiel Anmerkung .An example of a simple map application that adds an annotation to a map An example annotation added to a map

Bevor Sie sich mit dieser APP befassen, sehen Sie sich die .net-Ereignisse unter der UIKit an.Before tackling this app, let’s get started by looking at .NET events under the UIKit.

.Net-Ereignisse mit UIKit.NET Events with UIKit

Xamarin. IOS macht .net-Ereignisse für UIKit-Steuerelemente verfügbar.Xamarin.iOS exposes .NET events on UIKit controls. UIButton hat z. b. ein touchupinside-Ereignis, das Sie wie in .NET verwenden, wie im folgenden Code gezeigt, in dem ein c#-Lambda-Ausdruck verwendet wird:For example, UIButton has a TouchUpInside event, which you handle as you normally would in .NET, as shown in the following code that uses a C# lambda expression:

aButton.TouchUpInside += (o,s) => {
    Console.WriteLine("button touched");
};

Sie können dies auch mit einer anonymen c# 2,0-Methode implementieren, die wie folgt aussieht:You could also implement this with a C# 2.0-style anonymous method like this one:

aButton.TouchUpInside += delegate {
    Console.WriteLine ("button touched");
};

Der vorangehende Code wird in der- ViewDidLoad Methode von UIViewController eingebunden.The preceding code is wired up in the ViewDidLoad method of the UIViewController. Die aButton Variable verweist auf eine Schaltfläche, die Sie entweder im IOS-Designer oder mit Code hinzufügen können.The aButton variable references a button, which you could add either in the iOS Designer or with code. Die folgende Abbildung zeigt eine Schaltfläche, die im IOS-Designer hinzugefügt wurde:The following figure shows a button that has been added in the iOS Designer:

Eine im IOS-Designer hinzugefügte SchaltflächeA button added in iOS Designer

Xamarin. IOS unterstützt auch den Ziel Aktions Stil der Verbindung Ihres Codes mit einer Interaktion, die mit einem-Steuerelement auftritt.Xamarin.iOS also supports the target-action style of connecting your code to an interaction that occurs with a control. Um eine Ziel Aktion für die Schaltfläche " Hello " zu erstellen, doppelklicken Sie im IOS-Designer darauf.To create a target-action for the Hello button, double click it in the iOS Designer. Die Code-Behind-Datei von UIViewController wird angezeigt, und der Entwickler wird aufgefordert, einen Speicherort zum Einfügen der Verbindungsmethode auszuwählen:The UIViewController's code-behind file will be displayed and the developer will be asked to select a location to insert the connecting method:

Die Code Behind-Datei uiviewcontrollersThe UIViewControllers code-behind file

Nachdem Sie einen Speicherort ausgewählt haben, wird eine neue Methode erstellt und mit dem Steuerelement verknüpft.After a location is selected, a new method is created and wired-up to the control. Im folgenden Beispiel wird eine Meldung in die Konsole geschrieben, wenn auf die Schaltfläche geklickt wird:In the following example, a message will be written to the console when the button is clicked:

Wenn auf die Schaltfläche geklickt wird, wird eine Meldung in die Konsole geschrieben.A message will be written to the console when the button is clicked

Weitere Informationen zum IOS-Ziel Aktions Muster finden Sie im Abschnitt "target-Action" unter Haupt Anwendungs Kompetenzen für IOS in der IOS-Entwickler Bibliothek von Apple.For more details about the iOS target-action pattern, see the Target-Action section of Core Application Competencies for iOS in Apple’s iOS Developer Library.

Weitere Informationen zur Verwendung des IOS-Designers mit xamarin. IOS finden Sie in der Übersicht über den IOS-Designer .For more information about how to use the iOS Designer with Xamarin.iOS, see the iOS Designer Overview documentation.

EventsEvents

Wenn Sie Ereignisse von UIControl abfangen möchten, stehen Ihnen verschiedene Optionen zur Auswahl: von der Verwendung der c#-Lambdas und der Delegatfunktionen bis zur Verwendung der Low-Level-Ziel-C-APIs.If you want to intercept events from UIControl, you have a range of options: from using the C# lambdas and delegate functions to using the low-level Objective-C APIs.

Der folgende Abschnitt zeigt, wie Sie das Touchdown-Ereignis auf einer Schaltfläche erfassen, je nachdem, wie viel Kontrolle Sie benötigen.The following section shows how you would capture the TouchDown event on a button, depending on how much control you need.

C#-StilC# Style

Verwenden der delegatsyntax:Using the delegate syntax:

UIButton button = MakeTheButton ();
button.TouchDown += delegate {
    Console.WriteLine ("Touched");
};

Wenn Sie stattdessen Lambdas verwenden möchten:If you like lambdas instead:

button.TouchDown += () => {
   Console.WriteLine ("Touched");
};

Wenn Sie mehrere Schaltflächen verwenden möchten, verwenden Sie denselben Handler, um denselben Code gemeinsam zu verwenden:If you want to have multiple buttons use the same handler to share the same code:

void handler (object sender, EventArgs args)
{
   if (sender == button1)
      Console.WriteLine ("button1");
   else
      Console.WriteLine ("some other button");
}

button1.TouchDown += handler;
button2.TouchDown += handler;

Überwachen von mehr als einer Art von EreignisMonitoring more than one kind of Event

Die c#-Ereignisse für uicontrolevent-Flags haben eine eins-zu-Eins-Zuordnung zu einzelnen Flags.The C# events for UIControlEvent flags have a one-to-one mapping to individual flags. Verwenden Sie die-Methode, wenn Sie über denselben Code verfügen möchten, der zwei oder mehr Ereignisse behandelt UIControl.AddTarget :When you want to have the same piece of code handle two or more events, use the UIControl.AddTarget method:

button.AddTarget (handler, UIControlEvent.TouchDown | UIControlEvent.TouchCancel);

Verwenden der Lambda-Syntax:Using the lambda syntax:

button.AddTarget ((sender, event)=> Console.WriteLine ("An event happened"), UIControlEvent.TouchDown | UIControlEvent.TouchCancel);

Wenn Sie Funktionen von Ziel-C auf niedriger Ebene verwenden müssen, z. b. mit einer bestimmten Objektinstanz verknüpfen und eine bestimmte Auswahl aufrufen:If you need to use low-level features of Objective-C, like hooking up to a particular object instance and invoking a particular selector:

[Export ("MySelector")]
void MyObjectiveCHandler ()
{
    Console.WriteLine ("Hello!");
}

// In some other place:

button.AddTarget (this, new Selector ("MySelector"), UIControlEvent.TouchDown);

Beachten Sie, dass es sich um eine öffentliche Methode handeln muss, wenn Sie die Instanzmethode in einer geerbten Basisklasse implementieren.Please note, if you implement the instance method in an inherited base class, it must be a public method.

ProtokolleProtocols

Bei einem Protokoll handelt es sich um eine Programmiersprache, die eine Liste von Methoden Deklarationen bereitstellt.A protocol is an Objective-C language feature that provides a list of method declarations. Dies dient einem ähnlichen Zweck wie eine Schnittstelle in c#. der Hauptunterschied besteht darin, dass ein Protokoll optionale Methoden aufweisen kann.It serves a similar purpose to an interface in C#, the main difference being that a protocol can have optional methods. Optionale Methoden werden nicht aufgerufen, wenn die Klasse, die ein Protokoll annimmt, Sie nicht implementiert.Optional methods are not called if the class that adopts a protocol does not implement them. Außerdem kann eine einzelne Klasse in "Ziel-C" mehrere Protokolle implementieren, ebenso wie eine c#-Klasse mehrere Schnittstellen implementieren kann.Also, a single class in Objective-C can implement multiple protocols, just as a C# class can implement multiple interfaces.

Apple verwendet Protokolle in Ios, um Verträge für zu über mittelende Klassen zu definieren, während gleichzeitig die implementierende Klasse vom Aufrufer entfernt wird, sodass Sie genau wie eine c#-Schnittstelle funktioniert.Apple uses protocols throughout iOS to define contracts for classes to adopt, while abstracting away the implementing class from the caller, thus operating just like a C# interface. Protokolle werden sowohl in nicht-delegatszenarios (z. b. im MKAnnotation folgenden Beispiel) als auch mit Delegaten (wie weiter unten in diesem Dokument im delegatenabschnitt dargestellt) verwendet.Protocols are used both in non-delegate scenarios (such as with the MKAnnotation example shown next), and with delegates (as presented later in this document, in the Delegates section).

Protokolle mit xamarin. IOSProtocols with Xamarin.ios

Werfen wir einen Blick auf ein Beispiel, das ein Ziel-C-Protokoll von xamarin. IOS verwendet.Let’s take a look at an example using an Objective-C protocol from Xamarin.iOS. In diesem Beispiel verwenden wir das MKAnnotation Protokoll, das Teil des MapKit Frameworks ist.For this example, we’ll use the MKAnnotation protocol, which is part of the MapKit framework. MKAnnotationein Protokoll, mit dem jedes Objekt, das es annimmt, Informationen zu einer Anmerkung bereitstellen kann, die einer Zuordnung hinzugefügt werden kann.MKAnnotation is a protocol that allows any object that adopts it to provide information about an annotation that can be added to a map. Ein Objekt, das implementiert, MKAnnotation stellt z. b. den Speicherort der Anmerkung und den ihm zugeordneten Titel bereit.For example, an object implementing MKAnnotation provides the location of the annotation and the title associated with it.

Auf diese Weise wird das MKAnnotation Protokoll verwendet, um relevante Daten bereitzustellen, die mit einer Anmerkung einhergehen.In this way, the MKAnnotation protocol is used to provide pertinent data that accompanies an annotation. Die tatsächliche Ansicht für die Anmerkung selbst wird aus den Daten im Objekt erstellt, das das Protokoll annimmt MKAnnotation .The actual view for the annotation itself is built from the data in the object that adopts the MKAnnotation protocol. Beispielsweise wird der Text für die Legende, der angezeigt wird, wenn der Benutzer auf die-Anmerkung tippt (wie im nachfolgenden Screenshot gezeigt), von der- Title Eigenschaft in der-Klasse abgeleitet, die das Protokoll implementiert:For example, the text for the callout that appears when the user taps on the annotation (as shown in the screenshot below) comes from the Title property in the class that implements the protocol:

Beispiel Text für die Legende, wenn der Benutzer auf die Anmerkung tipptExample text for the callout when the user taps on the annotation

Wie im nächsten Abschnitt beschrieben, werden Protokolle in Deep Dive, xamarin. IOS, an abstrakte Klassen gebunden.As described in the next section, Protocols Deep Dive, Xamarin.iOS binds protocols to abstract classes. Für das MKAnnotation Protokoll wird die gebundene c#-Klasse so benannt, dass MKAnnotation Sie den Namen des Protokolls imitiert, und Sie ist eine Unterklasse von NSObject , der Basisklasse für cocoatouch.For the MKAnnotation protocol, the bound C# class is named MKAnnotation to mimic the name of the protocol, and it is a subclass of NSObject, the root base class for CocoaTouch. Das Protokoll erfordert, dass ein Getter und ein Setter für die Koordinate implementiert werden. ein Titel und Untertitel sind jedoch optional.The protocol requires a getter and setter to be implemented for the coordinate; however, a title and subtitle are optional. Daher ist in der- MKAnnotation Klasse die Coordinate -Eigenschaft abstraktund erfordert, dass Sie implementiert wird und die Title -Eigenschaft und die-Eigenschaft Subtitle als virtuellgekennzeichnet sind, sodass Sie optional sind, wie unten dargestellt:Therefore, in the MKAnnotation class, the Coordinate property is abstract, requiring it to be implemented and the Title and Subtitle properties are marked virtual, making them optional, as shown below:

[Register ("MKAnnotation"), Model ]
public abstract class MKAnnotation : NSObject
{
    public abstract CLLocationCoordinate2D Coordinate
    {
        [Export ("coordinate")]
        get;
        [Export ("setCoordinate:")]
        set;
    }

    public virtual string Title
    {
        [Export ("title")]
        get
        {
            throw new ModelNotImplementedException ();
        }
    }

    public virtual string Subtitle
    {
        [Export ("subtitle")]
        get
        {
            throw new ModelNotImplementedException ();
        }
    }
...
}

Jede Klasse kann Anmerkung-Daten durch einfaches Ableiten von bereitstellen, solange mindestens MKAnnotation die- Coordinate Eigenschaft implementiert ist.Any class can provide annotation data by simply deriving from MKAnnotation, as long as at least the Coordinate property is implemented. Im folgenden finden Sie eine Beispiel Klasse, die die-Koordinate im Konstruktor annimmt und eine Zeichenfolge für den Titel zurückgibt:For example, here’s a sample class that takes the coordinate in the constructor and returns a string for the title:

/// <summary>
/// Annotation class that subclasses MKAnnotation abstract class
/// MKAnnotation is bound by Xamarin.iOS to the MKAnnotation protocol
/// </summary>
public class SampleMapAnnotation : MKAnnotation
{
    string title;

    public SampleMapAnnotation (CLLocationCoordinate2D coordinate)
    {
        Coordinate = coordinate;
        title = "Sample";
    }

    public override CLLocationCoordinate2D Coordinate { get; set; }

    public override string Title {
        get {
            return title;
        }
    }
}

Durch das Protokoll, an das es gebunden ist, kann jede Klasse, die Unterklassen MKAnnotation relevante Daten bereitstellen, die von der Zuordnung verwendet werden, wenn die Ansicht der Anmerkung erstellt wird.Through the protocol it is bound to, any class that subclasses MKAnnotation can provide relevant data that will be used by the map when it creates the annotation’s view. Um einer Zuordnung eine Anmerkung hinzuzufügen, nennen Sie einfach die-Methode einer- AddAnnotation MKMapView Instanz, wie im folgenden Code gezeigt:To add an annotation to a map, simply call the AddAnnotation method of an MKMapView instance, as shown in the following code:

//an arbitrary coordinate used for demonstration here
var sampleCoordinate =
    new CLLocationCoordinate2D (42.3467512, -71.0969456); // Boston

//create an annotation and add it to the map
map.AddAnnotation (new SampleMapAnnotation (sampleCoordinate));

Bei der hier angegebenen Karten Variablen handelt es sich um eine Instanz von MKMapView , die die-Klasse darstellt, die die Karte selbst darstellt.The map variable here is an instance of an MKMapView, which is the class that represents the map itself. MKMapViewVerwendet die Coordinate Daten, die von der- SampleMapAnnotation Instanz abgeleitet werden, um die Anmerkung-Ansicht auf der Karte zu positionieren.The MKMapView will use the Coordinate data derived from the SampleMapAnnotation instance to position the annotation view on the map.

Das MKAnnotation Protokoll bietet einen bekannten Satz von Funktionen für alle Objekte, die es implementieren, ohne dass der Consumer (in diesem Fall die Zuordnung) über Implementierungsdetails wissen muss.The MKAnnotation protocol provides a known set of capabilities across any objects that implement it, without the consumer (the map in this case) needing to know about implementation details. Dadurch wird das Hinzufügen einer Vielzahl möglicher Anmerkungen zu einer Karte optimiert.This streamlines adding a variety of possible annotations to a map.

Ausführliche Informationen zu ProtokollenProtocols Deep Dive

Da c#-Schnittstellen keine optionalen Methoden unterstützen, ordnet xamarin. IOS Protokolle abstrakten Klassen zu.Since C# interfaces don’t support optional methods, Xamarin.iOS maps protocols to abstract classes. Daher wird die Übernahme eines Protokolls in Ziel-C in xamarin. IOS durch Ableiten von der abstrakten-Klasse, die an das Protokoll gebunden ist, und Implementieren der erforderlichen Methoden erreicht.Therefore, adopting a protocol in Objective-C is accomplished in Xamarin.iOS by deriving from the abstract class that is bound to the protocol and implementing the required methods. Diese Methoden werden als abstrakte Methoden in der-Klasse verfügbar gemacht.These methods will be exposed as abstract methods in the class. Optionale Methoden aus dem Protokoll werden an virtuelle Methoden der c#-Klasse gebunden.Optional methods from the protocol will be bound to virtual methods of the C# class.

Hier sehen Sie z. b. einen Teil des Protokolls, der UITableViewDataSource in xamarin. IOS gebunden ist:For example, here is a portion of the UITableViewDataSource protocol as bound in Xamarin.iOS:

public abstract class UITableViewDataSource : NSObject
{
    [Export ("tableView:cellForRowAtIndexPath:")]
    public abstract UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath);
    [Export ("numberOfSectionsInTableView:")]
    public virtual int NumberOfSections (UITableView tableView){...}
...
}

Beachten Sie, dass die-Klasse abstrakt ist.Note that the class is abstract. Xamarin. IOS macht die-Klasse abstrakt, um optionale/erforderliche Methoden in Protokollen zu unterstützen.Xamarin.iOS makes the class abstract to support optional/required methods in protocols. Anders als bei Ziel-C-Protokollen (oder c#-Schnittstellen) unterstützen c#-Klassen jedoch nicht die mehrfache Vererbung.However, unlike Objective-C protocols, (or C# interfaces), C# classes don’t support multiple inheritance. Dies wirkt sich auf den Entwurf von c#-Code aus, der Protokolle verwendet, und führt in der Regel zu den Klassen.This affects the design of C# code that uses protocols, and typically leads to nested classes. Weitere Informationen zu diesem Problem finden Sie weiter unten in diesem Dokument im Abschnitt Delegaten.More about this issue is covered later in this document, in the Delegates section.

GetCell(…)ist eine abstrakte Methode, die an den Ziel-C- Selektorgebunden ist, bei tableView:cellForRowAtIndexPath: dem es sich um eine erforderliche Methode des UITableViewDataSource Protokolls handelt.GetCell(…) is an abstract method, bound to the Objective-C selector, tableView:cellForRowAtIndexPath:, which is a required method of the UITableViewDataSource protocol. Selector ist der Begriff "Ziel-C" für den Methodennamen.Selector is the Objective-C term for method name. Um die Methode nach Bedarf zu erzwingen, deklariert xamarin. IOS Sie als abstrakt.To enforce the method as required, Xamarin.iOS declares it as abstract. Die andere Methode, NumberOfSections(…) , ist an gebunden numberOfSectionsInTableview: .The other method, NumberOfSections(…), is bound to numberOfSectionsInTableview:. Diese Methode ist im Protokoll optional, sodass xamarin. IOS Sie als virtuell deklariert, sodass es optional ist, in c# zu überschreiben.This method is optional in the protocol, so Xamarin.iOS declares it as virtual, making it optional to override in C#.

Xamarin. IOS kümmert sich um alle IOS-Bindungen.Xamarin.iOS takes care of all iOS binding for you. Wenn Sie jedoch jemals ein Protokoll manuell von Ziel-C binden müssen, können Sie dazu eine Klasse mit dem versehen ExportAttribute .However, if you ever need to bind a protocol from Objective-C manually, you can do so by decorating a class with the ExportAttribute. Dabei handelt es sich um dieselbe Methode, die auch von xamarin. IOS selbst verwendet wird.This is the same method used by Xamarin.iOS itself.

Weitere Informationen zum Binden von Ziel-c-Typen in xamarin. IOS finden Sie im Artikel Binden von Ziel-c-Typen.For more information about how to bind Objective-C types in Xamarin.iOS, see the article Binding Objective-C Types.

Wir sind jedoch noch nicht mit Protokollen vertraut.We’re not through with protocols yet, though. Sie werden auch in ios als Grundlage für Ziel-C-Delegaten verwendet. Dies ist das Thema des nächsten Abschnitts.They’re also used in iOS as the basis for Objective-C delegates, which is the topic of the next section.

DelegatenDelegates

IOS verwendet Ziel-C-Delegaten, um das Delegierungs Muster zu implementieren, in dem ein Objekt die Arbeit an eine andere übergibt.iOS uses Objective-C delegates to implement the delegation pattern, in which one object passes work off to another. Das Objekt, das die Arbeit leistet, ist der Delegat des ersten Objekts.The object doing the work is the delegate of the first object. Ein-Objekt weist seinen Delegaten an, Aufgaben auszuführen, indem es ihm Nachrichten sendet, nachdem bestimmte Dinge auftreten.An object tells its delegate to do work by sending it messages after certain things happen. Das Senden einer Nachricht wie dieser in Ziel-C ist funktional äquivalent zum Aufrufen einer Methode in c#.Sending a message like this in Objective-C is functionally equivalent to calling a method in C#. Ein Delegat implementiert Methoden als Reaktion auf diese Aufrufe und stellt somit Funktionen für die Anwendung bereit.A delegate implements methods in response to these calls, and so provides functionality to the application.

Delegaten ermöglichen es Ihnen, das Verhalten von Klassen zu erweitern, ohne Unterklassen erstellen zu müssen.Delegates enable you to extend the behavior of classes without needing to create subclasses. Anwendungen in ios verwenden häufig Delegaten, wenn eine Klasse nach einer wichtigen Aktion an eine andere zurückgibt.Applications in iOS often use delegates when one class calls back to another after an important action occurs. Beispielsweise ruft die- MKMapView Klasse den Delegaten zurück, wenn der Benutzer auf eine Anmerkung in einer Zuordnung tippt, und gibt dem Autor der Delegatklasse die Möglichkeit, innerhalb der Anwendung zu antworten.For example, the MKMapView class calls back to its delegate when the user taps an annotation on a map, giving the author of the delegate class the opportunity to respond within the application. Ein Beispiel für diese Art der delegatverwendung finden Sie weiter unten in diesem Artikel, z. b. mit einem Delegaten mit xamarin. IOS.You can work through an example of this type of delegate usage later in this article, in Example Using a Delegate with Xamarin.iOS.

An diesem Punkt Fragen Sie sich vielleicht, wie eine Klasse bestimmt, welche Methoden für Ihren Delegaten aufgerufen werden müssen.At this point, you may be wondering how a class determines what methods to call on its delegate. Dies ist ein weiterer Ort, an dem Sie Protokolle verwenden.This is another place where you use protocols. Normalerweise stammen die Methoden, die für einen Delegaten verfügbar sind, von den Protokollen, die Sie übernehmenUsually, the methods available for a delegate come from the protocols they adopt.

Verwendung von Protokollen mit DelegatenHow Protocols are used with Delegates

Wir haben bereits gesehen, wie Protokolle verwendet werden, um das Hinzufügen von Anmerkungen zu einer Karte zu unterstützen.We saw earlier how protocols are used to support adding annotations to a map. Protokolle werden auch zum Bereitstellen eines bekannten Satzes von Methoden für Klassen verwendet, die nach bestimmten Ereignissen aufgerufen werden können, z. b. Nachdem der Benutzer auf eine Anmerkung in einer Karte tippt oder eine Zelle in einer Tabelle ausgewählt hat.Protocols are also used to provide a known set of methods for classes to call after certain events occur, such as after the user taps an annotation on a map or selects a cell in a table. Die Klassen, die diese Methoden implementieren, werden als Delegaten der Klassen bezeichnet, die diese Methoden aufzurufen.The classes that implement these methods are known as the delegates of the classes that call them.

Klassen, die die Delegierung unterstützen, machen eine delegateigenschaft verfügbar, der eine Klasse zugewiesen ist, die den Delegaten implementiert.Classes that support delegation do so by exposing a Delegate property, to which a class implementing the delegate is assigned. Die Methoden, die Sie für den Delegaten implementieren, hängen von dem Protokoll ab, das der jeweilige Delegat annimmt.The methods you implement for the delegate will depend upon the protocol that the particular delegate adopts. Für die- UITableView Methode implementieren Sie das UITableViewDelegate -Protokoll für die UIAccelerometer -Methode, die Sie implementieren UIAccelerometerDelegate , usw. für alle anderen Klassen in Ios, für die Sie einen Delegaten verfügbar machen möchten.For the UITableView method, you implement the UITableViewDelegate protocol, for the UIAccelerometer method, you would implement UIAccelerometerDelegate, and so on for any other classes throughout iOS for which you would want to expose a delegate.

Die MKMapView Klasse, die wir in unserem vorherigen Beispiel gesehen haben, verfügt auch über eine Eigenschaft namens "Delegat", die nach dem Auftreten verschiedener Ereignisse aufgerufen wird.The MKMapView class we saw in our earlier example also has a property called Delegate, which it will call after various events occur. Der Delegat für MKMapView ist vom Typ MKMapViewDelegate .The Delegate for MKMapView is of type MKMapViewDelegate. Dies wird in Kürze in einem Beispiel verwendet, um auf die-Anmerkung zu reagieren, nachdem Sie ausgewählt wurde, aber zunächst wird der Unterschied zwischen starken und schwachen Delegaten erörtert.You’ll use this shortly in an example to respond to the annotation after it is selected, but first let’s discuss the difference between strong and weak delegates.

Starke Delegaten im Vergleich zu schwachen DelegatenStrong Delegates vs. Weak Delegates

Die bisher untersuchten Delegaten sind starke Delegaten, was bedeutet, dass Sie stark typisiert sind.The delegates we’ve looked at so far are strong delegates, meaning they are strongly typed. Die xamarin. IOS-Bindungen liefern eine stark typisierte Klasse für jedes delegatprotokoll in ios.The Xamarin.iOS bindings ship with a strongly typed class for every delegate protocol in iOS. IOS hat jedoch auch das Konzept eines schwachen Delegaten.However, iOS also has the concept of a weak delegate. Anstatt eine Klasse zu Unterklassen, die an das Ziel-C-Protokoll für einen bestimmten Delegaten gebunden ist, können Sie mit IOS auch die Protokoll Methoden selbst an eine beliebige Klasse binden, die von NSObject abgeleitet ist, ihre Methoden mit dem Export Attribute versehen und dann die entsprechenden Selektoren bereitstellt.Instead of subclassing a class bound to the Objective-C protocol for a particular delegate, iOS also lets you choose to bind the protocol methods yourself in any class you like that derives from NSObject, decorating your methods with the ExportAttribute, and then supplying the appropriate selectors. Wenn Sie diesen Ansatz verwenden, weisen Sie der weakdelegateigenschaft anstelle der delegateigenschaft eine Instanz der Klasse zu.When you take this approach, you assign an instance of your class to the WeakDelegate property instead of to the Delegate property. Ein schwacher Delegat bietet Ihnen die Flexibilität, ihre Delegatklasse in eine andere Vererbungs Hierarchie zu bringen.A weak delegate offers you the flexibility to take your delegate class down a different inheritance hierarchy. Sehen wir uns ein xamarin. IOS-Beispiel an, in dem sowohl starke als auch schwache Delegaten verwendet werden.Let’s look at a Xamarin.iOS example that uses both strong and weak delegates.

Beispiel für die Verwendung eines Delegaten mit xamarin. IOSExample Using a Delegate with Xamarin.iOS

Um Code als Reaktion auf den Benutzer auszuführen, der in unserem Beispiel auf die-Anmerkung tippt, können wir eine-Klasse Unterklassen MKMapViewDelegate und der MKMapView -Eigenschaft von eine-Instanz zuweisen Delegate .To execute code in response to the user tapping the annotation in our example, we can subclass MKMapViewDelegate and assign an instance to the MKMapView’s Delegate property. Das MKMapViewDelegate Protokoll enthält nur optionale Methoden.The MKMapViewDelegate protocol contains only optional methods. Daher sind alle Methoden virtuell, die an dieses Protokoll in der xamarin. IOS-Klasse gebunden sind MKMapViewDelegate .Therefore, all the methods are virtual that are bound to this protocol in the Xamarin.iOS MKMapViewDelegate class. Wenn der Benutzer eine Anmerkung auswählt, MKMapView sendet die Instanz die mapView:didSelectAnnotationView: Nachricht an Ihren Delegaten.When the user selects an annotation, the MKMapView instance will send the mapView:didSelectAnnotationView: message to its delegate. Um dies in xamarin. IOS zu behandeln, müssen wir die- DidSelectAnnotationView (MKMapView mapView, MKAnnotationView annotationView) Methode in der mkmapviewdelegat-unter Klasse wie folgt überschreiben:To handle this in Xamarin.iOS, we need to override the DidSelectAnnotationView (MKMapView mapView, MKAnnotationView annotationView) method in the MKMapViewDelegate subclass like this:

public class SampleMapDelegate : MKMapViewDelegate
{
    public override void DidSelectAnnotationView (
        MKMapView mapView, MKAnnotationView annotationView)
    {
        var sampleAnnotation =
            annotationView.Annotation as SampleMapAnnotation;

        if (sampleAnnotation != null) {

            //demo accessing the coordinate of the selected annotation to
            //zoom in on it
            mapView.Region = MKCoordinateRegion.FromDistance(
                sampleAnnotation.Coordinate, 500, 500);

            //demo accessing the title of the selected annotation
            Console.WriteLine ("{0} was tapped", sampleAnnotation.Title);
        }
    }
}

Die oben gezeigte samplemapdelegatklasse wird als eine geclusterte Klasse im Controller implementiert, der die MKMapView Instanz enthält.The SampleMapDelegate class shown above is implemented as a nested class in the controller that contains the MKMapView instance. In Ziel-C sehen Sie häufig, dass der Controller mehrere Protokolle direkt innerhalb der Klasse übernehmen kann.In Objective-C, you’ll often see the controller adopt multiple protocols directly within the class. Da Protokolle jedoch an Klassen in xamarin. IOS gebunden sind, werden die Klassen, die stark typisierte Delegaten implementieren, in der Regel als Klassen eingefügt.However, since protocols are bound to classes in Xamarin.iOS, the classes that implement strongly typed delegates are usually included as nested classes.

Wenn die Implementierung der Delegatklasse vorhanden ist, müssen Sie nur eine Instanz des Delegaten im Controller instanziieren und Sie der-Eigenschaft des-Delegaten zuweisen, MKMapView Delegate wie hier gezeigt:With the delegate class implementation in place, you only need to instantiate an instance of the delegate in the controller and assign it to the MKMapView’s Delegate property as shown here:

public partial class Protocols_Delegates_EventsViewController : UIViewController
{
    SampleMapDelegate _mapDelegate;
    ...
    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();

        //set the map's delegate
        _mapDelegate = new SampleMapDelegate ();
        map.Delegate = _mapDelegate;
        ...
    }
    class SampleMapDelegate : MKMapViewDelegate
    {
        ...
    }
}

Wenn Sie einen schwachen Delegaten zum gleichen Zweck verwenden möchten, müssen Sie die Methode selbst an eine beliebige Klasse binden, die von abgeleitet ist, NSObject und Sie der-Eigenschaft der-Klasse zuweisen WeakDelegate MKMapView .To use a weak delegate to accomplish the same thing, you need to bind the method yourself in any class that derives from NSObject and assign it to the WeakDelegate property of the MKMapView. Da die- UIViewController Klasse letztendlich von abgeleitet NSObject wird (wie jede Ziel-C-Klasse in cocoatouch), können wir einfach eine Methode implementieren, die mapView:didSelectAnnotationView: direkt an den Controller gebunden ist, und den Controller dem Controller zuweisen, sodass die zusätzliche, nicht erforderliche Klasse nicht MKMapView WeakDelegate mehr benötigt wird.Since the UIViewController class ultimately derives from NSObject (like every Objective-C class in CocoaTouch), we can simply implement a method bound to mapView:didSelectAnnotationView: directly in the controller and assign the controller to MKMapView’s WeakDelegate, avoiding the need for the extra nested class. Der folgende Code veranschaulicht diese Vorgehensweise:The code below demonstrates this approach:

public partial class Protocols_Delegates_EventsViewController : UIViewController
{
    ...
    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
        //assign the controller directly to the weak delegate
        map.WeakDelegate = this;
    }
    //bind to the Objective-C selector mapView:didSelectAnnotationView:
    [Export("mapView:didSelectAnnotationView:")]
    public void DidSelectAnnotationView (MKMapView mapView,
        MKAnnotationView annotationView)
    {
        ...
    }
}

Wenn Sie diesen Code ausführen, verhält sich die Anwendung genau so wie beim Ausführen der stark typisierten delegatversion.When running this code, the application behaves exactly as it did when running the strongly typed delegate version. Der Vorteil dieses Codes besteht darin, dass der schwache Delegat nicht die Erstellung der zusätzlichen Klasse erfordert, die erstellt wurde, als der stark typisierte Delegat verwendet wurde.The benefit from this code is that the weak delegate doesn’t require the creation of the extra class that was created when we used the strongly typed delegate. Dies erfolgt jedoch auf Kosten der Typsicherheit.However, this comes at the expense of type safety. Wenn Sie einen Fehler in der Auswahl treffen würden, die an das-Modul übermittelt wurde ExportAttribute , können Sie bis zur Laufzeit nicht ermitteln.If you were to make a mistake in the selector that was passed to the ExportAttribute, you wouldn’t find out until runtime.

Ereignisse und DelegatenEvents and Delegates

Delegaten werden für Rückrufe in ios ähnlich der Art und Weise verwendet, in der .net Ereignisse verwendet.Delegates are used for callbacks in iOS similarly to the way .NET uses events. Um IOS-APIs und die Verwendung von Ziel-C-Delegaten zu ermöglichen, werden .net-Ereignisse an vielen Stellen angezeigt, an denen Delegaten in ios verwendet werden.To make iOS APIs and the way they use Objective-C delegates seem more like .NET, Xamarin.iOS exposes .NET events in many places where delegates are used in iOS.

Beispielsweise könnte die frühere Implementierung, bei der der MKMapViewDelegate auf eine ausgewählte Anmerkung geantwortet hat, auch in xamarin. IOS mithilfe eines .net-Ereignisses implementiert werden.For example, the earlier implementation where the MKMapViewDelegate responded to a selected annotation could also be implemented in Xamarin.iOS by using a .NET event. In diesem Fall würde das Ereignis in definiert MKMapView und aufgerufen werden DidSelectAnnotationView .In that case, the event would be defined in MKMapView and called DidSelectAnnotationView. Sie verfügt über eine EventArgs Unterklasse des Typs MKMapViewAnnotationEventsArgs .It would have an EventArgs subclass of type MKMapViewAnnotationEventsArgs. Mit der- View Eigenschaft von MKMapViewAnnotationEventsArgs erhalten Sie einen Verweis auf die Anmerkung-Ansicht, von der aus Sie mit derselben Implementierung fortfahren können, die Sie zuvor gesehen haben:The View property of MKMapViewAnnotationEventsArgs would give you a reference to the annotation view, from which you could proceed with the same implementation you had earlier, as illustrated here:

map.DidSelectAnnotationView += (s,e) => {
    var sampleAnnotation = e.View.Annotation as SampleMapAnnotation;
    if (sampleAnnotation != null) {
        //demo accessing the coordinate of the selected annotation to
        //zoom in on it
        mapView.Region = MKCoordinateRegion.FromDistance (
            sampleAnnotation.Coordinate, 500, 500);

        //demo accessing the title of the selected annotation
        Console.WriteLine ("{0} was tapped", sampleAnnotation.Title);
    }
};

ZusammenfassungSummary

In diesem Artikel wurde beschrieben, wie Ereignisse, Protokolle und Delegaten in xamarin. IOS verwendet werden.This article covered how to use events, protocols, and delegates in Xamarin.iOS. Wir haben gesehen, wie xamarin. IOS normale .net-Stil Ereignisse für Steuerelemente verfügbar macht.We saw how Xamarin.iOS exposes normal .NET style events for controls. Als nächstes haben wir uns mit den Zielen der Ziele C vertraut gemacht, einschließlich der Unterschiede zwischen c#-Schnittstellen und der Verwendung von xamarin. IOS.Next we learned about Objective-C protocols, including how they are different from C# interfaces and how Xamarin.iOS uses them. Schließlich haben wir die Ziel-C-Delegaten aus einer xamarin. IOS-Perspektive untersucht.Finally, we examined Objective-C delegates from a Xamarin.iOS perspective. Wir haben gesehen, wie xamarin. IOS sowohl starke als auch schwach typisierte Delegaten unterstützt und wie .net-Ereignisse an Delegatmethoden gebunden werden.We saw how Xamarin.iOS supports both strongly and weakly typed delegates, and how to bind .NET events to delegate methods.