Frage

Ich weiß, wie die Delegierten arbeiten, und ich weiß, wie kann ich sie nutzen.

Aber wie kann ich sie erstellen?

War es hilfreich?

Lösung

Ein Objective-C Delegat ist ein Objekt, das ein anderes Objekt in der delegate Eigenschaft zugeordnet wurde. So erstellen Sie ein, legen Sie einfach eine Klasse, die die Delegierten Methoden implementiert denen Sie interessiert sind, und diese Klasse markieren, wie die Delegierten-Protokoll implementiert.

Zum Beispiel: Angenommen, Sie eine UIWebView haben. Wenn Sie möchten, dass seine Delegierten webViewDidStartLoad: Methode Sie eine Klasse wie folgt erstellen können:

@interface MyClass<UIWebViewDelegate>
// ...
@end

@implementation MyClass
- (void)webViewDidStartLoad:(UIWebView *)webView { 
    // ... 
}
@end

Dann könnte man eine Instanz von MyClass erstellen und als die Delegierten Web-Ansicht zuweisen:

MyClass *instanceOfMyClass = [[MyClass alloc] init];
myWebView.delegate = instanceOfMyClass;

Auf der UIWebView Seite, hat es wahrscheinlich Code ähnlich wie diese zu sehen, ob die Delegierten auf die webViewDidStartLoad: Nachricht antworten mit respondsToSelector: und es gegebenenfalls senden

if([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
    [self.delegate webViewDidStartLoad:self];
}

Der Delegierte Eigenschaft selbst ist in der Regel erklärt weak (in ARC) oder assign (pre-ARC) Schleifen zu vermeiden behalten, da die Delegierten eines Objekts häufig auf dieses Objekt eine starke Referenz hält. (Zum Beispiel kann ein View-Controller ist oft der Delegat einer Ansicht enthält.)

machen Delegierten für Ihre Klassen

Ihre eigenen Delegierten zu definieren, werden Sie ihre Methoden irgendwo erklären müssen, wie in der Apple-Docs auf Protokolle . Sie erklären, in der Regel ein formelles Protokoll. Die Erklärung von UIWebView.h umschrieben, würde wie folgt aussehen:

@protocol UIWebViewDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end

Dies ist analog zu einer Schnittstelle oder abstrakte Basisklasse, da sie eine spezielle Art für Ihre Stellvertretung, UIWebViewDelegate in diesem Fall schafft. Delegieren Implementierer würde dieses Protokoll zu übernehmen:

@interface MyClass <UIWebViewDelegate>
// ...
@end

Und dann die Methoden in dem Protokoll implementieren. Für Verfahren im Protokoll als @optional erklärt (wie die meisten Delegatmethoden), müssen Sie mit -respondsToSelector: überprüfen, bevor eine bestimmte Methode auf sie anrufen.

Naming

Delegate Methoden werden typischerweise genannt bei der delegierenden Klassennamen beginnen, und nehmen Sie die delegierenden Objekt als ersten Parameter. Sie verwenden auch oft eine Willen, should- oder DID-Form. Also, webViewDidStartLoad: (erster Parameter ist die Web-Ansicht) statt loadStarted zum Beispiel (keine Parameter nehmen).

Geschwindigkeit Optimizations

Statt zu prüfen, ob ein Delegierter an einen Selektor Nachricht jedes Mal, wenn wir wollen, antwortet er, können Sie diese Informationen zwischenzuspeichern, wenn die Delegierten festgelegt werden. Eine sehr saubere Art und Weise, dies zu tun, ist ein Bitfeld zu verwenden, wie folgt:

@protocol SomethingDelegate <NSObject>
@optional
- (void)something:(id)something didFinishLoadingItem:(id)item;
- (void)something:(id)something didFailWithError:(NSError *)error;
@end

@interface Something : NSObject
@property (nonatomic, weak) id <SomethingDelegate> delegate;
@end

@implementation Something {
  struct {
    unsigned int didFinishLoadingItem:1;
    unsigned int didFailWithError:1;
  } delegateRespondsTo;
}
@synthesize delegate;

- (void)setDelegate:(id <SomethingDelegate>)aDelegate {
  if (delegate != aDelegate) {
    delegate = aDelegate;

    delegateRespondsTo.didFinishLoadingItem = [delegate respondsToSelector:@selector(something:didFinishLoadingItem:)];
    delegateRespondsTo.didFailWithError = [delegate respondsToSelector:@selector(something:didFailWithError:)];
  }
}
@end

Dann im Körper, können wir überprüfen, dass unsere Delegierten verarbeitet Nachrichten von unserem delegateRespondsTo struct zugreifen, anstatt durch das Senden -respondsToSelector: immer und immer wieder.

Informal Delegierten

Vor Protokolle existierte, war es üblich, eine

Andere Tipps

Die zugelassene Antwort ist groß, aber wenn Sie nach einer 1-minütigen Antwort versuchen, diese suchen:

MyClass.h Datei sollte wie folgt aussehen (fügen Sie delegieren Linien mit Kommentaren!)

#import <BlaClass/BlaClass.h>

@class MyClass;             //define class, so protocol can see MyClass
@protocol MyClassDelegate <NSObject>   //define delegate protocol
    - (void) myClassDelegateMethod: (MyClass *) sender;  //define delegate method to be implemented within another class
@end //end protocol

@interface MyClass : NSObject {
}
@property (nonatomic, weak) id <MyClassDelegate> delegate; //define MyClassDelegate as delegate

@end

MyClass.m Datei sollte wie folgt aussehen

#import "MyClass.h"
@implementation MyClass 
@synthesize delegate; //synthesise  MyClassDelegate delegate

- (void) myMethodToDoStuff {
    [self.delegate myClassDelegateMethod:self]; //this will call the method implemented in your other class    
}

@end

Um die Delegierten in einer anderen Klasse zu verwenden (UIViewController genannt MyVC in diesem Fall) MyVC.h:

#import "MyClass.h"
@interface MyVC:UIViewController <MyClassDelegate> { //make it a delegate for MyClassDelegate
}

MyVC.m:

myClass.delegate = self;          //set its delegate to self somewhere

Delegatmethode Implementieren

- (void) myClassDelegateMethod: (MyClass *) sender {
    NSLog(@"Delegates are great!");
}

Wenn die formalen Protokollverfahren unter Verwendung von Delegierten Unterstützung für das Erstellen, ich habe festgestellt, dass Sie die richtige Art Überprüfung sicherstellen können (wenn auch, Laufzeit, keine Zeit kompilieren) durch Zusatz von etwas wie:

if (![delegate conformsToProtocol:@protocol(MyDelegate)]) {
    [NSException raise:@"MyDelegate Exception"
                format:@"Parameter does not conform to MyDelegate protocol at line %d", (int)__LINE__];
}

in Ihrem Delegaten Accessor (setDelegate) Code. Dies hilft, Fehler zu minimieren.

Vielleicht ist dies mehr entlang der Linien von dem, was Sie fehlen:

Wenn Sie von einem C ++ wie Sicht kommen, nehmen die Delegierten ein wenig gewöhnungsbedürftig - aber im Grunde ‚sie gerade arbeiten.‘

Das System funktioniert so, dass Sie einige Objekt festgelegt, die Sie als Vertreter der NSWindow schrieb, aber Ihre Aufgabe hat nur Implementierungen (Methoden) für ein oder ein paar der vielen möglichen Delegatmethoden. So etwas passiert, und NSWindow will, um Ihr Objekt nennen - es Objective-c der respondsToSelector Methode nur verwendet, um zu bestimmen, ob Ihr Objekt will genannt, dass die Methode, und dann nennt. Dies ist, wie Objective-C arbeitet - Methoden auf Anfrage nachgeschlagen werden.

Es ist völlig trivial dies mit Ihren eigenen Objekten zu tun, gibt es nichts Besonderes los, man könnte zum Beispiel eine NSArray von 27 Objekten hat, alle verschiedene Arten von Objekten, nur 18 einige von ihnen mit -(void)setToBue; das Verfahren die anderen 9 nicht. So setToBlue auf allen 18 aufzurufen, müssen es getan, so etwas wie folgt aus:

for (id anObject in myArray)
{
  if ([anObject respondsToSelector:@selector(@"setToBlue")])
     [anObject setToBlue]; 
}

Die andere Sache, über die Delegierten, dass sie nicht zurückgehalten werden, so dass Sie immer die Delegierten setzen müssen in Ihrer nil Methode MyClass dealloc.

Als gute Praxis von Apple empfohlen, es ist gut für die Delegaten (das ist ein Protokoll, per Definition), um NSObject Protokoll zu entsprechen.

@protocol MyDelegate <NSObject>
    ...
@end

& optionale Methoden in Ihrem Delegat (das heißt Methoden, die werden nicht notwendigerweise implementiert) zu erstellen, können Sie die @optional Anmerkung wie folgt verwenden:

@protocol MyDelegate <NSObject>
    ...
    ...
      // Declaration for Methods that 'must' be implemented'
    ...
    ...
    @optional
    ...
      // Declaration for Methods that 'need not necessarily' be implemented by the class conforming to your delegate
    ...
@end

Wenn also Methoden, die Sie als optional angegeben haben, müssen Sie (in Ihrer Klasse) mit respondsToSelector prüfen, ob die Ansicht (die zu Ihrem Delegaten konform) hat Ihre optionale Methode tatsächlich umgesetzt (n) oder nicht.

Ich denke, all diese Antworten sehr viel Sinn machen, wenn Sie die Delegierten verstehen. Persönlich war ich aus dem Land der C / C ++ und vor diesen Verfahrenssprache wie Fortran etc, so ist hier mein 2 min nimmt auf der Suche nach ähnlichen Analoga in C ++ Paradigma.

Wenn ich die Delegierten zu einem C ++ / Java-Programmierer zu erklären, würde ich sagen

Was sind die Delegierten? Dies sind statische Zeiger auf Klassen in einer anderen Klasse. Sobald Sie einen Zeiger zuweisen, können Sie Funktionen / Methoden in dieser Klasse nennen. Daher einige Funktionen Ihrer Klasse „delegiert“ (In C ++ Welt - Zeiger auf eine Klasse Objektzeiger). Zu einer anderen Klasse

Was sind Protokolle? Konzeptionell dient es als ähnlichen Zweck wie in die Header-Datei der Klasse, die Sie als Delegierter Klasse zuweisen. Ein Protokoll ist eine explizite Art und Weise zu definieren, welche Methoden in der Klasse implementiert werden muss, die Zeiger ist wurde als Delegierter innerhalb einer Klasse.

Wie kann ich etwas ähnliches in C ++? Wenn Sie versucht, dies in C ++ zu tun, würden Sie durch Zeiger auf Klassen (Objekte) in der Klassendefinition definieren und verdrahten sie dann zu anderen Klassen bis die zusätzliche Funktionen als Delegierte für Ihre Basisklasse bieten. Aber diese Verdrahtung muss innerhalb des Codes zu maitained und wird ungeschickt und fehleranfällig. Objective C geht davon aus, dass nur Programmierer sind nicht am besten auf diese decipline beibehalten und bietet Compiler Einschränkungen eine saubere Implementierung zu erzwingen.

Swift Version

Ein Delegierter ist nur eine Klasse, die einige Arbeit für eine andere Klasse der Fall ist. Lesen Sie den folgenden Code für ein etwas albern (aber hoffentlich erhellende) Spielplatz Beispiel, das zeigt, wie dies in Swift durchgeführt wird.

// A protocol is just a list of methods (and/or properties) that must
// be used by any class that adopts the protocol.
protocol OlderSiblingDelegate: class {
    // This protocol only defines one required method
    func getYourNiceOlderSiblingAGlassOfWater() -> String
}

class BossyBigBrother {

    // The delegate is the BossyBigBrother's slave. This position can 
    // be assigned later to whoever is available (and conforms to the 
    // protocol).
    weak var delegate: OlderSiblingDelegate?

    func tellSomebodyToGetMeSomeWater() -> String? {
        // The delegate is optional because there might not be anyone
        // nearby to boss around.
        return delegate?.getYourNiceOlderSiblingAGlassOfWater()
    }
}

// PoorLittleSister conforms to the OlderSiblingDelegate protocol
class PoorLittleSister: OlderSiblingDelegate {

    // This method is repquired by the protocol, but the protocol said
    // nothing about how it needs to be implemented.
    func getYourNiceOlderSiblingAGlassOfWater() -> String {
        return "Go get it yourself!"
    }

}

// initialize the classes
let bigBro = BossyBigBrother()
let lilSis = PoorLittleSister()

// Set the delegate 
// bigBro could boss around anyone who conforms to the 
// OlderSiblingDelegate protocol, but since lilSis is here, 
// she is the unlucky choice.
bigBro.delegate = lilSis

// Because the delegate is set, there is a class to do bigBro's work for him.
// bigBro tells lilSis to get him some water.
if let replyFromLilSis = bigBro.tellSomebodyToGetMeSomeWater() {
    print(replyFromLilSis) // "Go get it yourself!"
}

In der Praxis Delegierten oft werden in den folgenden Situationen verwendet

  1. Wenn eine Klasse braucht einige Informationen zu einer anderen Klasse zu kommunizieren
  2. Wenn eine Klasse will eine andere Klasse ermöglichen es anpassen

Die Klassen müssen nicht alles über sie wissen vorher, außer dass die Delegierten Klasse entspricht das erforderliche Protokoll.

Ich empfehle die beiden folgenden Artikel zu lesen. Sie halfen mir Delegierten verstehen sogar besser als die Dokumentation haben.

Ok, das ist nicht wirklich eine Antwort auf die Frage, aber wenn Sie schauen nach oben, wie Sie Ihre eigenen Delegierten machen vielleicht etwas viel einfacher könnte eine bessere Antwort für Sie sein.

ich implementieren kaum meine Delegierten, weil ich selten benötigen. Ich kann nur einen Delegierten für einen Delegatobjekt haben. Also, wenn Sie Ihre Stellvertretung für eine Einwegkommunikation / Übergabe von Daten, als Sie viel besser mit Benachrichtigungen ist.

NSNotification können Objekte an mehrere Empfänger weitergeben, und es ist sehr einfach zu bedienen. Es funktioniert wie folgt:

MyClass.m Datei sollte wie folgt aussehen

#import "MyClass.h"
@implementation MyClass 

- (void) myMethodToDoStuff {
//this will post a notification with myClassData (NSArray in this case)  in its userInfo dict and self as an object
[[NSNotificationCenter defaultCenter] postNotificationName:@"myClassUpdatedData"
                                                    object:self
                                                  userInfo:[NSDictionary dictionaryWithObject:selectedLocation[@"myClassData"] forKey:@"myClassData"]];
}
@end

Um Ihre Anmeldung in anderen Klassen zu verwenden: In Klasse als Beobachter:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(otherClassUpdatedItsData:) name:@"myClassUpdatedData" object:nil];

die Wahl implementieren:

- (void) otherClassUpdatedItsData:(NSNotification *)note {
    NSLog(@"*** Other class updated its data ***");
    MyClass *otherClass = [note object];  //the object itself, you can call back any selector if you want
    NSArray *otherClassData = [note userInfo][@"myClassData"]; //get myClass data object and do whatever you want with it
}

Vergessen Sie nicht, Ihre Klasse als Beobachter zu entfernen, wenn

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

Sie können sagen, eine Klasse, die Sie entwickelt und möchten einen Delegaten Eigentum erklären, um es zu benachrichtigen, wenn ein Ereignis passiert:

@class myClass;

@protocol myClassDelegate <NSObject>

-(void)myClass:(MyClass*)myObject requiredEventHandlerWithParameter:(ParamType*)param;

@optional
-(void)myClass:(MyClass*)myObject optionalEventHandlerWithParameter:(ParamType*)param;

@end


@interface MyClass : NSObject

@property(nonatomic,weak)id< MyClassDelegate> delegate;

@end

, so dass Sie ein Protokoll in MyClass Header-Datei (oder eine separate Header-Datei) erklären und erklären die erforderlichen / optional Event-Handler, die Ihre Stellvertretung muss / implementieren sollten, erklärt dann eine Eigenschaft in MyClass vom Typ (id< MyClassDelegate>), was bedeutet, jeden Ziel c-Klasse, die das Protokoll MyClassDelegate entspricht, werden Sie feststellen, dass die Delegierten Eigenschaft als schwach deklariert wird, das ist sehr wichtig Zyklus zu verhindern behalten (meistens behält die Stellvertretung die MyClass Instanz so, wenn Sie die Delegierten erklärten, wie behalten, sowohl von ihnen werden sich gegenseitig und keiner von ihnen jemals veröffentlicht werden).

behalten

werden Sie auch feststellen, dass die Protokollmethoden an die Delegaten als Parameter die MyClass Instanz gehen, ist dies für den Fall, Best Practice der Delegierten wollen einige Methoden auf MyClass Instanz anrufen und helfen auch, wenn die Delegierten mich als MyClassDelegate auf mehrere MyClass erklärt Instanzen, wie wenn Sie mehrere UITableView's Instanzen in Ihrem ViewController haben und erklärt sich als UITableViewDelegate für alle von ihnen.

und in Ihrem MyClass benachrichtigen Sie den Delegaten mit deklarierten Ereignisse wie folgt:

if([_delegate respondsToSelector:@selector(myClass: requiredEventHandlerWithParameter:)])
{
     [_delegate myClass:self requiredEventHandlerWithParameter:(ParamType*)param];
}

Sie zunächst überprüfen, ob Ihr Delegierter des Protokollverfahrens reagiert, dass Sie im Begriff sind, für den Fall, rufen die Delegierten es nicht implementieren und die App stürzt dann (auch wenn das Protokollverfahren erforderlich ist).

Dies ist eine einfache Methode, die Delegierten erstellen

Erstellen Protokoll in .h-Datei. Stellen Sie sicher, dass vor dem Protokoll definiert ist @class gefolgt von dem Namen des UIViewController < As the protocol I am going to use is UIViewController class>.

mit

Schritt: 1: Erstellen Sie eine neue Klasse Protocol „YourViewController“ genannt, die die Unterklasse von UIViewController Klasse sein werden, und diese Klasse mit dem zweiten Viewcontroller zuweisen.

Schritt 2: Gehen Sie auf die "YourViewController" Datei und ändern Sie es wie folgt:

#import <UIKit/UIkit.h>
@class YourViewController;

@protocol YourViewController Delegate <NSObject>

 @optional
-(void)defineDelegateMethodName: (YourViewController *) controller;

@required
-(BOOL)delegateMethodReturningBool: (YourViewController *) controller;

  @end
  @interface YourViewController : UIViewController

  //Since the property for the protocol could be of any class, then it will be marked as a type of id.

  @property (nonatomic, weak) id< YourViewController Delegate> delegate;

@end

Die definierten Methoden in dem Protokollverhalten mit @optional @required und als Teil der Protokolldefinition gesteuert werden können.

Schritt 3: Die Umsetzung der Delegierten

    #import "delegate.h"

   @interface YourDelegateUser ()
     <YourViewControllerDelegate>
   @end

   @implementation YourDelegateUser

   - (void) variousFoo {
      YourViewController *controller = [[YourViewController alloc] init];
      controller.delegate = self;
   }

   -(void)defineDelegateMethodName: (YourViewController *) controller {
      // handle the delegate being called here
   }

   -(BOOL)delegateMethodReturningBool: (YourViewController *) controller {
      // handle the delegate being called here
      return YES;
   }

   @end

// Test, ob die Methode definiert wurde, bevor Sie es nennen

 - (void) someMethodToCallDelegate {
     if ([[self delegate] respondsToSelector:@selector(defineDelegateMethodName:)]) {
           [self.delegate delegateMethodName:self]; 
     }
  }

Ihre eigenen Delegierten erstellen, müssen Sie zunächst ein Protokoll erstellen und die erforderlichen Methoden zu erklären, ohne zu implementieren. Und dann implementieren dieses Protokoll in die Header-Klasse, wo Sie die Delegierten oder Delegatmethoden implementieren möchten.

Ein Protokoll muss wie unten angegeben werden:

@protocol ServiceResponceDelegate <NSObject>

- (void) serviceDidFailWithRequestType:(NSString*)error;
- (void) serviceDidFinishedSucessfully:(NSString*)success;

@end

Dies ist der Service-Klasse, wo einige Aufgabe getan werden sollte. Es zeigt, wie Delegierten zu definieren und, wie der Delegaten einzustellen. In der Implementierungsklasse nach der Aufgabe der Delegierten sind die Verfahren abgeschlossen sind genannt.

@interface ServiceClass : NSObject
{
id <ServiceResponceDelegate> _delegate;
}

- (void) setDelegate:(id)delegate;
- (void) someTask;

@end

@implementation ServiceClass

- (void) setDelegate:(id)delegate
{
_delegate = delegate;
}

- (void) someTask
{
/*

   perform task

*/
if (!success)
{
[_delegate serviceDidFailWithRequestType:@”task failed”];
}
else
{
[_delegate serviceDidFinishedSucessfully:@”task success”];
}
}
@end

Dies ist die Hauptansichtsklasse, von wo aus der Serviceklasse, indem die Delegierten selbst genannt wird. Und auch das Protokoll in der Header-Klasse implementiert wird.

@interface viewController: UIViewController <ServiceResponceDelegate>
{
ServiceClass* _service;
}

- (void) go;

@end

@implementation viewController

//
//some methods
//

- (void) go
{
_service = [[ServiceClass alloc] init];
[_service setDelegate:self];
[_service someTask];
}

Das ist es, und Delegatmethoden in dieser Klasse durch die Implementierung, wird die Steuerung zurückkommen, sobald der Betrieb / Aufgabe erledigt ist.

Disclaimer: Dies ist die Swift Version, wie eine delegate erstellen

.

Also, was sind die Delegierten? ... in der Softwareentwicklung, gibt es allgemeine wiederverwendbare Lösungsarchitekturen, die häufig auftretende Probleme in einem bestimmten Kontext, diese „Vorlagen“, so zu lösen helfen zu sprechen, als Entwurfsmuster bekannt. Die Delegierten sind ein Design-Muster, das ein Objekt erlaubt es, Nachrichten an ein anderes Objekt zu senden, wenn ein bestimmtes Ereignis eintritt. Stellen Sie sich ein Objekt A ein Objekt B ruft eine Aktion auszuführen. Sobald der Vorgang abgeschlossen ist, sollte ein Objekt weiß, dass B die Aufgabe abgeschlossen ist und die notwendige Aktion, dies mit Hilfe der Delegierten erreicht werden kann!

Für eine bessere Erklärung, werde ich Ihnen zeigen, wie ein benutzerdefiniert Delegierten erstellen, die Daten zwischen den Klassen geht, mit Swift in einer einfachen Anwendung, starten durch das Herunterladen oder dieses Starter Projekt klonen und führen sie es!

Sie können eine App mit zwei Klassen, ViewController A und ViewController B sehen. B hat zwei Ansichten, die die Hintergrundfarbe des ViewController vom Fass ändern, nichts zu kompliziert oder? auch jetzt lassen Sie dachte, dass auf einfache Weise auch die Hintergrundfarbe der Klasse A zu ändern, wenn die Ansichten über Klasse B abgegriffen werden.

Das Problem ist, dass diese Ansichten Teil der Klasse B und haben keine Ahnung von der Klasse A sind, also müssen wir einen Weg finden, zwischen diesen beiden Klassen zu kommunizieren, und das ist, wo eine Delegation scheint. Ich teilte die Umsetzung in 6 Schritten, so dass Sie dies als Spickzettel verwenden können, wenn Sie es brauchen.

Schritt 1: Geben Sie für die Pragma Marke Schritt 1 in ClassBVC Datei und fügen Sie diese

//MARK: step 1 Add Protocol here.
protocol ClassBVCDelegate: class {
func changeBackgroundColor(_ color: UIColor?)
}

Der erste Schritt ist ein protocol, in diesem Fall zu schaffen, werden wir das Protokoll in der Klasse B, innerhalb des Protokolls erstellen können Sie so viele Funktionen erstellen, die Sie auf den Anforderungen Ihrer Implementierung basieren sollen. In diesem Fall haben wir nur eine einfache Funktion, die eine optionale UIColor als Argument akzeptiert. Ist eine gute Praxis, um Ihre Protokolle Hinzufügen des Wort delegate am Ende des Klassennamen zu nennen, in diesem Fall ClassBVCDelegate.

Schritt 2: Geben Sie für die Pragma Marke Schritt 2 in ClassVBC und fügen Sie diese

//MARK: step 2 Create a delegate property here.
weak var delegate: ClassBVCDelegate?

Hier haben wir nur einen Delegierten Eigenschaft für die Klasse erstellen, müssen diese Eigenschaft den protocol Typ annehmen, und es sollte optional sein. Außerdem sollen Sie das schwache Schlüsselwort vor der Eigenschaft in den Zyklen und potenzielle Speicherlecks zu vermeiden behalten, wenn Sie nicht wissen, was das bedeutet keine Sorge für jetzt, nur nicht vergessen, dieses Schlüsselwort hinzuzufügen.

Schritt 3: Suchen Sie nach dem Pragma Marke Schritt 3 innerhalb des handleTap method in ClassBVC und fügen Sie diese

//MARK: step 3 Add the delegate method call here.
delegate?.changeBackgroundColor(tapGesture.view?.backgroundColor)

Eine Sache, die Sie sollten die App und tippen Sie auf einem beliebigen Ansicht wissen, laufen, werden Sie keine neue Verhalten sehen, und das ist richtig, aber das, was ich will, ist darauf hinzuweisen, dass der App es Absturz ist nicht, wenn der Delegat ist genannt, und es ist, weil wir es als optionaler Wert zu schaffen und deshalb ist es noch nicht einmal die delegierte nicht vorhanden abstürzen. Lassen Sie uns jetzt Datei ClassAVC gehen und machen es, die delegiert werden.

Schritt 4: Geben Sie für den Pragma Marke Schritt 4 innerhalb der handleTap Methode in ClassAVC und fügen Sie diese neben dem Klassentyp wie diese

.
//MARK: step 4 conform the protocol here.
class ClassAVC: UIViewController, ClassBVCDelegate {
}

Jetzt angenommen ClassAVC das ClassBVCDelegate Protokoll, können Sie sehen, dass Ihr Compiler einen Fehler geben, der sagt „Typ‚ClassAVC entspricht nicht Protokoll ‚ClassBVCDelegate‘ und das bedeutet nur, dass Sie nicht die Methoden des Protokolls verwendet haben noch vorstellen, dass, wenn die Klasse A das Protokoll nimmt einen Vertrag mit der Klasse B ist wie die Unterzeichnung und dieser Vertrag sagt: „Jede Klasse Annahme muss ich meine Funktionen nutzen!“

Kurze Anmerkung: Wenn Sie von einem Objective-C Hintergrund kommen, werden Sie wahrscheinlich denken, dass Sie auch shut up, dass Fehler, dass Verfahren optional zu machen, aber für meine Überraschung, und wahrscheinlich bei Ihnen, nicht Swift Sprache nicht optional protocols unterstützen, wenn Sie es tun wollen, können Sie eine Erweiterung für Ihren protocol oder verwenden Sie das @objc Keyword in Ihrer protocol Implementierung erstellen .

Wenn ich persönlich ein Protokoll mit verschiedenen optionalen Methoden erstellen haben würde ich es in verschiedene protocols zu brechen bevorzugen, dass die Art, wie ich das Konzept des Gebens eine einzige Verantwortung meiner Objekten folgen, aber es kann auf dem spezifischen variiert Umsetzung.

hier ist ein guter Artikel über optionale Methoden .

Schritt 5: Suchen Sie nach dem Pragma Marke Schritt 5 innerhalb der Vorbereitung für segue Methode und fügen Sie diese

//MARK: step 5 create a reference of Class B and bind them through the `prepareforsegue` method.
if let nav = segue.destination as? UINavigationController, let classBVC = nav.topViewController as? ClassBVC {
classBVC.delegate = self
}

Hier schaffen wir nur eine Instanz von ClassBVC und weisen ihre Delegierten selbst, aber was ist hier selbst? gut, Selbst ist die ClassAVC, die übertragen wurde!

Schritt 6: Schließlich sucht der Pragma Schritt 6 in ClassAVC und lassen Sie uns die Funktionen des protocol verwenden, starten Sie die Eingabe func changeBackgroundColor und Sie werden sehen, dass es Auto-Vervollständigung es für Sie. Sie können eine beliebige Implementierung hinzufügen darin, in diesem Beispiel, werden wir nur die Hintergrundfarbe ändern, fügen Sie diese.

//MARK: step 6 finally use the method of the contract
func changeBackgroundColor(_ color: UIColor?) {
view.backgroundColor = color
}

Jetzt laufen die App!

Delegates sind überall und man sie wahrscheinlich verwenden, ohne einmal bemerken, wenn Sie einen tableview in der Vergangenheit erstellen Sie Delegation verwendet wird, arbeiten viele Klassen von UIKIT um sie herum und zu vielen anderen frameworks, sie diese Hauptprobleme zu lösen.

  • Vermeiden Sie enge Kopplung von Objekten.
  • Ändern Verhalten und Aussehen, ohne dass Objekte, Unterklasse.
  • Lassen Sie Aufgaben zu jedem beliebigen Objekt behandelt ausgeschaltet werden.

Herzlichen Glückwunsch, Sie haben soeben einen benutzerdefinierten Delegaten implementieren, ich weiß, dass Sie wahrscheinlich denken, so viel Mühe gerade dafür? na ja, ist Delegation ein sehr wichtiges Design-Muster zu verstehen, wenn Sie ein iOS Entwickler werden wollen, und immer im Auge behalten, dass sie 0.59 Beziehung zwischen Objekten haben.

Sie können die Original-Tutorial finden Sie unter hier

Antwort ist eigentlich beantwortet, aber ich möchte, um Ihnen einen „Spickzettel“ für das Erstellen eines Delegaten:

DELEGATE SCRIPT

CLASS A - Where delegate is calling function

@protocol <#Protocol Name#> <NSObject>

-(void)delegateMethod;

@end

@interface <#Some ViewController#> : <#UIViewController#> 

@property (nonatomic, assign) id <<#Protocol Name#>> delegate;

@end


@implementation <#Some ViewController#> 

-(void)someMethod {
    [self.delegate methodName];
}

@end




CLASS B - Where delegate is called 

@interface <#Other ViewController#> (<#Delegate Name#>) {}
@end

@implementation <#Other ViewController#> 

-(void)otherMethod {
    CLASSA *classA = [[CLASSA alloc] init];

    [classA setDelegate:self];
}

-delegateMethod() {

}

@end

ViewController.h

@protocol NameDelegate <NSObject>

-(void)delegateMEthod: (ArgType) arg;

@end

@property id <NameDelegate> delegate;

ViewController.m

[self.delegate delegateMEthod: argument];

MainViewController.m

ViewController viewController = [ViewController new];
viewController.delegate = self;

Methode:

-(void)delegateMEthod: (ArgType) arg{
}

In meiner Sicht erstellen separate Klasse für die delegierte Methode und Sie verwenden können, wo Sie wollen.

in meiner Gewohnheit DropDownClass.h

typedef enum
{
 DDSTATE,
 DDCITY
}DropDownType;

@protocol DropDownListDelegate <NSObject>
@required
- (void)dropDownDidSelectItemWithString:(NSString*)itemString     DropDownType:(DropDownType)dropDownType;
@end
@interface DropDownViewController : UIViewController
{
 BOOL isFiltered;
}
@property (nonatomic, assign) DropDownType dropDownType;
@property (weak) id <DropDownListDelegate> delegate;
@property (strong, nonatomic) NSMutableArray *array1DropDown;
@property (strong, nonatomic) NSMutableArray *array2DropDown;

danach in.m Datei erstellen Array mit Objekten,

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
CGFloat rowHeight = 44.0f;
return rowHeight;
}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return isFiltered?[self.array1DropDown count]:[self.array2DropDown count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = @"TableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}

if (self.delegate) {
    if (self.dropDownType == DDCITY) {
        cell.textLabel.text = [self.array1DropDown objectAtIndex:indexPath.row];
    }
    else if (self.dropDownType == DDSTATE) {
        cell.textLabel.text = [self.array2DropDown objectAtIndex:indexPath.row];
    }
}
return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
 [self dismissViewControllerAnimated:YES completion:^{
    if(self.delegate){
        if(self.dropDownType == DDCITY){
            [self.delegate dropDownDidSelectItemWithString:[self.array1DropDown objectAtIndex:indexPath.row] DropDownType:self.dropDownType];
        }
        else if (self.dropDownType == DDSTATE) {
            [self.delegate dropDownDidSelectItemWithString:[self.array2DropDown objectAtIndex:indexPath.row] DropDownType:self.dropDownType];
        }
    }
}];
}

Hier sind alle für Custom Delegat class.after gesetzt, dass Sie diese Delegatmethode verwenden können, wo Sie zB want.for ...

in meinem anderen Viewcontroller Import danach

erstellen Aktion für den Aufruf Delegatmethode wie folgt

- (IBAction)dropDownBtn1Action:(id)sender {
DropDownViewController *vehicleModelDropView = [[DropDownViewController alloc]init];
vehicleModelDropView.dropDownType = DDCITY;
vehicleModelDropView.delegate = self;
[self presentViewController:vehicleModelDropView animated:YES completion:nil];
}

danach Aufruf Delegatmethode wie diese

- (void)dropDownDidSelectItemWithString:(NSString *)itemString DropDownType:(DropDownType)dropDownType {
switch (dropDownType) {
    case DDCITY:{
        if(itemString.length > 0){
            //Here i am printing the selected row
            [self.dropDownBtn1 setTitle:itemString forState:UIControlStateNormal];
        }
    }
        break;
    case DDSTATE: {
        //Here i am printing the selected row
        [self.dropDownBtn2 setTitle:itemString forState:UIControlStateNormal];
    }

    default:
        break;
}
}

Delegieren: - Erstellen

@protocol addToCartDelegate <NSObject>

-(void)addToCartAction:(ItemsModel *)itemsModel isAdded:(BOOL)added;

@end

Senden und bitte zuweisen delegieren Sie senden die Daten anzuzeigen

[self.delegate addToCartAction:itemsModel isAdded:YES];
//1.
//Custom delegate 
@protocol TB_RemovedUserCellTag <NSObject>

-(void)didRemoveCellWithTag:(NSInteger)tag;

@end

//2.
//Create a weak reference in a class where you declared the delegate
@property(weak,nonatomic)id <TB_RemovedUserCellTag> removedCellTagDelegate;

//3. 
// use it in the class
  [self.removedCellTagDelegate didRemoveCellWithTag:self.tag];

//4. import the header file in the class where you want to conform to the protocol
@interface MyClassUsesDelegate ()<TB_RemovedUserCellTag>

@end

// 5. Implementieren Sie die Methode in der Klasse .m - (void) didRemoveCellWithTag: (NSInteger) tag {    NSLog @ ( "Tag% d", tag);

}

Lassen Sie sich mit einem Beispiel beginnen, wenn wir ein Produkt online kaufen, geht es durch Verfahren wie Versand / Lieferung von verschiedenem teams.So behandelt, wenn Versand abgeschlossen wird, soll Versandteam Lieferung Team benachrichtigen & es sollte 12.59 Kommunikation sein als diese Informationen sendet wäre Overhead für andere Personen / Verkäufer könnte erforderlich Menschen diese Informationen nur weitergeben wollen.

Also, wenn wir in Bezug auf unsere App denken, kann ein Ereignis, eine Online-Bestellung sein und verschiedene Teams wie mehrere Ansichten sein können.

Hier ist Code ShippingView als Versand Team & DeliveryView als Liefer Team vor:

//Declare the protocol with functions having info which needs to be communicated
protocol ShippingDelegate : class {
    func productShipped(productID : String)
}
//shippingView which shows shipping status of products
class ShippingView : UIView
{

    weak var delegate:ShippingDelegate?
    var productID : String

    @IBAction func checkShippingStatus(sender: UIButton)
    {
        // if product is shipped
        delegate?.productShipped(productID: productID)
    }
}
//Delivery view which shows delivery status & tracking info
class DeliveryView: UIView,ShippingDelegate
{
    func productShipped(productID : String)
    {
        // update status on view & perform delivery
    }
}

//Main page on app which has both views & shows updated info on product whole status
class ProductViewController : UIViewController
{
    var shippingView : ShippingView
    var deliveryView : DeliveryView

    override func viewDidLoad() {
        super.viewDidLoad()
        // as we want to update shipping info on delivery view, so assign delegate to delivery object
        // whenever shipping status gets updated it will call productShipped method in DeliveryView & update UI.
        shippingView.delegate = deliveryView
        //
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top