Wie erstelle ich Delegierten in Objective-C?

stimmen
683

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

Aber wie kann ich sie schaffen?

Veröffentlicht am 09/03/2009 um 17:06
quelle vom benutzer
In anderen Sprachen...                            


19 antworten

stimmen
852

Ein Objective-C delegieren ist ein Objekt , das mit der zugeordneten wurde eine delegateandere Objekteigenschaft. 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.

Angenommen, Sie haben ein UIWebView. Wenn Sie möchten , dass ihre Delegierten implementieren webViewDidStartLoad:Methode, könnten Sie eine Klasse wie folgt erstellen:

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

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

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

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

Auf der UIWebViewSeite, hat es wahrscheinlich Code ähnlich wie diese zu sehen , ob die Delegierten auf die reagiert webViewDidStartLoad:Nachricht mit respondsToSelector:und es gegebenenfalls zu 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 die Delegierten eine Ansicht sie enthält.)

Herstellung von Delegierten für Ihre Klassen

Um Ihre eigenen Delegierten zu definieren, werden Sie ihre Methoden irgendwo erklären müssen, wie in der diskutierten 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 schafft, UIWebViewDelegatein diesem Fall. Delegieren Implementierer würde dieses Protokoll zu verabschieden haben:

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

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

Benennung

Delegatmethoden sind in der Regel 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(wobei keine Parameter) zum Beispiel.

Speed ​​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 Zugriff auf delegateRespondsToStruktur, anstatt durch das Senden -respondsToSelector:immer und immer wieder.

informelle Delegierten

Vor Protokolle gab, war es üblich , eine verwenden Kategorie auf , NSObjectum die Verfahren zu erklären Delegierter implementieren könnte. Zum Beispiel CALayerhat noch dies:

@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end

Dies sagt im Wesentlichen den Compiler , dass jedes Objekt implementieren könnte displayLayer:.

Sie würden dann das gleiche verwenden -respondsToSelector:Ansatz , wie oben beschrieben , diese Methode zu nennen. Die Delegierten einfach diese Methode implementieren und die zuweisen delegateEigenschaft, und das ist es (es gibt keine erklären Sie ein Protokoll konform). Diese Methode ist in Apples Bibliotheken üblich, aber neue Code sollte die modernere Protokoll - Ansatz oben, da dieser Ansatz verunreinigt verwenden NSObject(was die automatische Vervollständigung weniger nützlich macht) und macht es schwierig für die Compiler Sie Tippfehler und ähnliche Fehler zu warnen.

Beantwortet am 09/03/2009 um 17:16
quelle vom benutzer

stimmen
360

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

MyClass.h Datei sollte wie folgt aussehen (Delegaten Linien mit Kommentaren hinzufügen!)

#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 Ihre Stellvertretung 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

Implementieren Delegatmethode

- (void) myClassDelegateMethod: (MyClass *) sender {
    NSLog(@"Delegates are great!");
}
Beantwortet am 30/09/2012 um 11:25
quelle vom benutzer

stimmen
18

Wenn die formale Protokoll-Methode für die Erstellung von Delegierten Unterstützung, habe ich festgestellt, dass Sie die richtige Art Prüfung (wenn auch, Laufzeit, keine Zeit kompilieren) gewährleisten, können durch Zugabe 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 Ihrer Stellvertretung Accessor (setDelegate) Code. Dies hilft, Fehler zu minimieren.

Beantwortet am 04/05/2010 um 21:42
quelle vom benutzer

stimmen
17

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

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

Das System funktioniert so , dass Sie einige Objekt festgelegt , die Sie als Vertreter der NSWindow schrieb, aber Ihr Objekt hat nur Implementierungen (Methoden) für ein oder ein paar der vielen möglichen Delegatmethoden. So etwas passiert, und NSWindowwill , um Ihr Objekt nennen - es nutzt nur Objective-C - respondsToSelectorMethode , 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 zu tun mit Ihren eigenen Objekten, gibt es nichts Besonderes los ist , Sie zum Beispiel eine haben könnte , NSArrayvon 27 Objekten, alle verschiedenen Arten von Objekten, nur 18 einige von ihnen das Verfahren mit -(void)setToBue;den anderen 9 nicht. So rufen setToBlueauf alle 18 , die brauchen 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 festlegen müssen nilin Ihrer MyClass deallocMethode.

Beantwortet am 10/03/2009 um 01:18
quelle vom benutzer

stimmen
16

Bitte! überprüfen unten einfach Schritt für Schritt Anleitung zu verstehen, wie Delegierten in iOS funktionieren.

Delegierter in iOS

Ich habe zwei Viewcontrollers erstellt (zum Senden von Daten von einem zum anderen)

  1. FirstViewController implementieren Delegierten (die Daten zur Verfügung stellt).
  2. SecondViewController erklären die Delegierten (die Daten erhalten).
Beantwortet am 27/02/2013 um 13:21
quelle vom benutzer

stimmen
15

Als gute Praxis von Apple empfohlen, ist es gut für die Delegierten (das ist ein Protokoll, per Definition), entsprechen NSObjectProtokoll.

@protocol MyDelegate <NSObject>
    ...
@end

& Optionale Methoden in Ihrem Delegat (dh Methoden , die nicht notwendigerweise realisiert werden) erstellen, können Sie die verwenden können @optionalAnmerkung wie folgt aus :

@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) überprüfen Sie mit , respondsToSelectorwenn die Ansicht (die zu Ihrem Delegaten konform) hat Ihre optionale Methode tatsächlich umgesetzt (n) oder nicht.

Beantwortet am 04/08/2013 um 09:39
quelle vom benutzer

stimmen
10

Ich denke, alle 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 erklären wäre, 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 werden einige Funktionen der Klasse „delegiert“ (In C ++ Welt - Zeiger auf ein Objekt der Klasse Zeiger) auf eine andere Klasse.

Welche 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.

Beantwortet am 19/06/2013 um 11:34
quelle vom benutzer

stimmen
9

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 erfolgt.

// 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 werden häufig Delegierten in den folgenden Situationen verwendet

  1. Wann ist eine Klasse einige Informationen zu einer anderen Klasse zu kommunizieren
  2. Wenn eine Klasse will eine andere Klasse erlauben, es zu gestalten

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

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

Beantwortet am 05/11/2015 um 17:11
quelle vom benutzer

stimmen
8

können sagen, dass Sie 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 deklarieren MyClassHeader - Datei (oder eine separate Header - Datei), und erklären die erforderlichen / optional Event - Handler , die Ihre Stellvertretung muss / sollte implementieren, dann eine Eigenschaft in deklarieren MyClassvom Typ ( id< MyClassDelegate>) , die jede objektive c - Klasse, entspricht das Protokoll MyClassDelegate, 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 MyClassInstanz so , wenn Sie den Delegierten erklärt , wie behalten, beide einander behalten und weder von ihnen wird jemals veröffentlicht werden).

Sie werden auch feststellen , dass das Protokoll Methoden , um die übergibt MyClassInstanz an die Delegaten als Parameter, das ist beste Praxis bei den Delegierten wollen einige Methoden auf aufrufe MyClassInstanz und helfen auch , wenn die Delegierten selbst als deklarieren , MyClassDelegateum mehrere MyClassInstanzen, wie wenn Sie mehrere haben UITableView'sInstanzen in Ihrem ViewControllerund erklärt sich als ein UITableViewDelegatefür alle von ihnen.

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

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

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

Beantwortet am 08/04/2015 um 13:24
quelle vom benutzer

stimmen
8

Ok, das ist nicht wirklich eine Antwort auf die Frage, aber wenn Sie nach oben suchen, 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];

Implementieren Sie die Wähler:

- (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];
}
Beantwortet am 17/07/2013 um 05:58
quelle vom benutzer

stimmen
6

Hier ist eine einfache Methode, die Delegierten zu erstellen

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

Schritt: 1: Erstellen Sie eine neue Klasse Protokoll namens „YourViewController“ , die die Unterklasse von UIViewController Klasse sein wird , 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 Verfahren in dem Protokollverhalten definiert ist, können mit @optional @required und als Teil der Protokolldefinition gesteuert werden.

Schritt 3: Durchführung 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]; 
     }
  }
Beantwortet am 29/09/2015 um 09:23
quelle vom benutzer

stimmen
5

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

Ein Protokoll muss, wie unten erklärt werden:

@protocol ServiceResponceDelegate <NSObject>

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

@end

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

@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.

@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.

Beantwortet am 03/08/2015 um 04:47
quelle vom benutzer

stimmen
1

Disclaimer: Dies ist die SwiftVersion, wie eine erstellen delegate.

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 das Objekt A weiß, dass B die Aufgabe und die notwendige Aktion abgeschlossen hat, kann dies mit Hilfe der Delegierten erreicht werden!

Zur besseren Erklärung, werde ich Ihnen zeigen , wie Sie eine benutzerdefinierte 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 sehen, ViewController Aund ViewController B. B hat zwei Ansichten , die die Hintergrundfarbe der vom Fass ändern ViewController, 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 zu schaffen protocol, in diesem Fall 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 akzeptiert UIColorals Argument. Ist eine gute Praxis , um Ihre Protokolle Hinzufügen des Wortes zu nennen delegateam Ende des Klassennamen, in diesem Fall ClassBVCDelegate.

Schritt 2: Geben Sie für die Pragma Marke Schritt 2 ClassVBCund 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, muss diese Eigenschaft den adoptieren protocolArt, und es sollte optional sein. Außerdem sollen Sie das schwache Schlüsselwort vor der Eigenschaft hinzufügen zu vermeiden Zyklen und potenzielle Speicherlecks 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 methodin ClassBVCund fügen Sie diese

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

Eine Sache , die Sie wissen sollten, führen Sie die App und tippen Sie auf einer beliebigen Ansicht, Sie werden keine neuen Verhalten sehen , und das ist richtig , aber die Sache , die ich darauf hinweisen möchte, ist , dass die App es nicht abstürzt , wenn der Delegat aufgerufen wird, und es ist , weil wir es als optionaler Wert zu schaffen und deshalb ist es noch nicht einmal die delegierte nicht vorhanden abstürzen. Gehen wir jetzt ClassAVCDatei und machen es, die delegiert.

Schritt 4: Geben Sie für die Pragma Marke Schritt 4 innerhalb des handleTap Verfahren ClassAVCund fügen Sie diese wie folgt auf Ihre Klassentyp nächsten.

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

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

Kurze Anmerkung: Wenn Sie aus einem Objective-CHintergrund , den Sie wahrscheinlich denken , dass Sie auch , dass Fehler zum Schweigen bringen können , dass Verfahren optional zu machen, aber für meine Überraschung, und wahrscheinlich bei Ihnen, der SwiftSprache nicht unterstützt optional protocols, wenn Sie es tun mögen , können Sie erstellen eine Erweiterung für Ihre protocoloder die @objc Keyword in Ihrer verwenden protocolUmsetzung.

Persönlich, wenn ich ein Protokoll mit verschiedenen optionalen Methoden erstellen muss ich es vorziehen würde es in verschiedenen zu brechen protocols, so habe ich das Konzept des Gebens einer einzigen Verantwortung meiner Objekte folgen, aber es kann von der spezifischen Implementierung variieren.

Hier ist ein guter Artikel über optionale Methoden.

5 Schritt: Geben Sie für die Pragma Marke Schritt 5 innerhalb der für Segue-Verfahren herzustellen 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 ClassBVCund weisen ihre Delegierten selbst, aber was ist hier selbst? na ja, selbst die , ClassAVCdie übertragen wurde!

Schritt 6: Schließlich sucht der Pragma Schritt 6 ClassAVCund lassen Sie uns die Funktionen des verwenden protocol, starten Sie func eingeben 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 läuft die App!

Delegatessind überall und sie nutzen sie wahrscheinlich nicht einmal bemerken, wenn Sie ein erstellen Sie tableviewin der Vergangenheit verwendet Delegation, viele Klassen von UIKITWerken um sie herum und viele andere frameworksauch, lösen sie diese Hauptprobleme.

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

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 eine werden wollen iOSEntwickler, und immer im Auge zu behalten , dass sie 0.59 Beziehung zwischen Objekten haben.

Sie können das Original - Tutorial sehen hier

Beantwortet am 26/04/2017 um 05:27
quelle vom benutzer

stimmen
1

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{
}
Beantwortet am 19/12/2016 um 04:14
quelle vom benutzer

stimmen
0

Die Antwort ist eigentlich beantwortet, aber ich möchte, um Ihnen einen „Spickzettel“ für die Erstellung 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
Beantwortet am 16/03/2018 um 04:40
quelle vom benutzer

stimmen
0

Beginnen wir mit einem Beispiel beginnen, wenn wir ein Produkt online kaufen, ist es wie Versand / Lieferung von verschiedenen teams.So behandelt durch Prozess geht beim Versenden abgeschlossen wird, sollten Versandteam Lieferung Team benachrichtigen & es diese Informationen 12.59 Kommunikation als Rundfunk sein wäre Aufwand für andere Personen / Anbieter, der diese Informationen nur erforderlich Menschen weitergeben möchten.

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 der Code ShippingView als Versand Team & DeliveryView als Liefer Team betrachten:

//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
        //
    }
}
Beantwortet am 14/07/2017 um 10:14
quelle vom benutzer

stimmen
0

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;

nach diesem in.m Datei-Array mit Objekten erstellen,

 - (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 Delegatmethode wie dieser Aufruf

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

nach diesem 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;
}
}
Beantwortet am 08/02/2017 um 09:30
quelle vom benutzer

stimmen
0
//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);

}

Beantwortet am 02/01/2017 um 16:31
quelle vom benutzer

stimmen
0

Delegieren: - Erstellen

@protocol addToCartDelegate <NSObject>

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

@end

Senden und bitte zuweisen Delegierten sehen Sie senden die Daten

[self.delegate addToCartAction:itemsModel isAdded:YES];
Beantwortet am 08/12/2016 um 10:50
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more