Cum pot crea delegati in Objective-C?

voturi
683

Știu cum funcționează delegați, și știu cum le pot folosi.

Dar cum le pot crea?

Întrebat 09/03/2009 la 17:06
sursa de către utilizator
În alte limbi...                            


19 răspunsuri

voturi
852

Un delegat Objective-C este un obiect care a fost atribuit la delegateproprietate un alt obiect. Pentru a crea unul, definiți pur și simplu o clasă care implementează metodele delegatului care vă interesează, și marchează acea clasă ca punerea în aplicare a protocolului delegat.

De exemplu, să presupunem că aveți un UIWebView. Dacă doriți să pună în aplicare delegatul său webViewDidStartLoad:metoda, ați putea crea o clasă de genul:

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

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

Apoi, ați putea crea o instanță de Clasa_Mea și atribuiți-o ca delegat vizualizarea web:

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

Pe UIWebViewpartea, are , probabil , cod similar cu acesta pentru a vedea dacă delegatul răspunde la webViewDidStartLoad:mesajul utilizând respondsToSelector:și trimiteți - l dacă este cazul.

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

Proprietatea delegat în sine este declarat în mod obișnuit weak(în ARC) sau assign(pre-ARC) pentru a evita să păstreze bucle, deoarece delegatul unui obiect deține adesea o referință puternică la acel obiect. (De exemplu, un controler de vedere este adesea delegatul vedere conține.)

Efectuarea de delegați pentru cursurile dvs.

Pentru a defini propriile delegati, va trebui să declare metodele lor undeva, așa cum sa discutat în Apple a Docs pe protocoale . Declari , de obicei , un protocol oficial. Declarația, parafrazate din UIWebView.h, ar arata astfel:

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

Acest lucru este analog cu o interfață sau o clasă de bază abstractă, deoarece creează un tip special pentru delegatul, UIWebViewDelegateîn acest caz. Implementatorii Delegați ar trebui să adopte acest protocol:

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

Și apoi pune în aplicare metodele în protocolul. Pentru metodele declarate în protocol ca @optional( la fel ca majoritatea metodelor delegatului), trebuie să verificați cu -respondsToSelector:înainte de a apela o metodă specială pe ea.

Denumire

Metodele Delegați sunt numite de obicei , incepand cu numele clasei de delegare, și să ia obiectul delegă ca primul parametru. De asemenea , ei folosesc adesea o formă will-, should- sau did-. Deci, webViewDidStartLoad:(primul parametru este vizualizarea web) , mai degrabă decât loadStarted(luând fără parametri) , de exemplu.

Optimizări de viteză

În loc de a verifica dacă un delegat răspunde la un selector de fiecare dată când vrem să-l mesaj, puteți cache informațiile atunci când sunt stabilite de delegați. O modalitate foarte curat de a face acest lucru este de a utiliza un bitfield, după cum urmează:

@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

Apoi, în organism, putem verifica dacă delegatul nostru se ocupă de mesaje prin accesarea nostru delegateRespondsTostruct, mai degrabă decât prin trimiterea de -respondsToSelector:peste si peste din nou.

Delegații informale

Înainte de protocoale a existat, era obișnuit să folosească o categorie privind NSObjectdeclararea metodelor un delegat ar putea pune în aplicare. De exemplu, CALayerîncă mai face acest lucru:

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

Aceasta spune , în esență , compilatorului că orice obiect ar putea pune în aplicare displayLayer:.

Tu ar folosi apoi aceeași -respondsToSelector:abordare descrisă mai sus pentru a apela la această metodă. Delegații pur și simplu să pună în aplicare această metodă și atribui delegateproprietatea, și asta e (nu exista nici o declarare a te conforma unui protocol). Această metodă este comună în bibliotecile Apple, dar noul cod ar trebui să utilizeze abordarea mai modern protocol de mai sus, deoarece această abordare poluează NSObject(ceea ce face mai puțin utile pentru completarea automată) și o face greu pentru compilator pentru a vă avertiza cu privire la erorile de scriere și de erori similare.

Publicat 09/03/2009 la 17:16
sursa de către utilizator

voturi
360

Răspunsul aprobat este mare, dar dacă sunteți în căutarea unui răspuns 1 minute încercați acest lucru:

fișier MyClass.h ar trebui să arate acest lucru (adăuga linii delegatului cu comentarii!)

#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

fișier MyClass.m ar trebui să arate așa

#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

Pentru a utiliza delegatul într-o altă clasă (UIViewController numit MyVC în acest caz) 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

Punerea în aplicare a metodei delegat

- (void) myClassDelegateMethod: (MyClass *) sender {
    NSLog(@"Delegates are great!");
}
Publicat 30/09/2012 la 11:25
sursa de către utilizator

voturi
18

Când se folosește metoda formală de protocol pentru crearea de sprijin delegat, am constatat că vă puteți asigura tipul adecvat de verificare (deși, în timpul rulării, nu timpul de compilare) prin adăugarea de ceva de genul:

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

în codul delegat accesor (setDelegate). Acest lucru ajută la minimizarea greșeli.

Publicat 04/05/2010 la 21:42
sursa de către utilizator

voturi
17

Poate că acest lucru este mai mult de-a lungul liniilor de ceea ce lipsesc:

Dacă provin dintr-un C ++ ca punct de vedere, delegati ia un pic obisnuirea pentru a - dar, în principiu, „ei doar locul de muncă“.

Modul în care funcționează este că ați setat un obiect pe care ai scris ca delegat la NSWindow, dar obiectul dvs. are doar implementari (metode) pentru una sau câteva dintre multele metode delegatului posibile. Deci se întâmplă ceva, și NSWindowvrea să cheme obiectului - se folosește doar Objective-C este respondsToSelectormetoda pentru a determina dacă obiectul dvs. dorește ca metodă numită și apoi o numește. Acesta este modul în care funcționează obiectiv-c - metode sunt privit în sus la cerere.

Este cu totul banal de a face acest lucru cu obiecte proprii, nu se întâmplă nimic deosebit, ai putea , de exemplu , au o NSArrayde 27 de obiecte, toate diferite tipuri de obiecte, doar 18 unele dintre ele având metoda -(void)setToBue;celelalte 9 nu. Deci , pentru a apela setToBluela toate 18 care au nevoie de făcut, ceva de genul:

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

Celălalt lucru despre delegați este că acestea nu sunt reținute, astfel încât să aibă întotdeauna să setați delegat la nilîn dumneavoastră MyClass deallocmetodă.

Publicat 10/03/2009 la 01:18
sursa de către utilizator

voturi
16

Vă rog! verificați mai jos simplu pas cu pas tutorial pentru a înțelege modul în care funcționează Delegații în iOS.

Delegat în iOS

Am creat două ViewControllers (pentru trimiterea datelor de la unul la altul)

  1. FirstViewController delegat să pună în aplicare (care furnizează date).
  2. SecondViewController declară delegatul (care va primi date).
Publicat 27/02/2013 la 13:21
sursa de către utilizator

voturi
15

Ca o bună practică recomandată de Apple, este bine pentru delegatul (care este un protocol, prin definiție), pentru a se conforma NSObjectprotocolului.

@protocol MyDelegate <NSObject>
    ...
@end

& Pentru a crea metode opționale din cadrul delegatul ( și anume metode care nu trebuie să fie neapărat puse în aplicare), puteți utiliza @optionaladnotarea ca aceasta:

@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

Deci , atunci când se utilizează metode pe care le - ați specificat ca opțional, trebuie să (în clasă) , verificați respondsToSelectordacă punctul de vedere (care este în conformitate cu delegatul) a pus în aplicare de fapt , metoda opțională (e) sau nu.

Publicat 04/08/2013 la 09:39
sursa de către utilizator

voturi
10

Cred că toate aceste răspunsuri fac o mulțime de sens odată ce ați înțeles delegați. Personal am venit din țara C / C ++ și înainte ca limbi procedurale, cum ar fi Fortran, etc asa ca aici este meu 2 minute ia pentru a gasi analogi similare în C ++ paradigma.

Dacă aș fi fost pentru a explica delegati la un C ++ / programator Java aș spune

Care sunt delegați? Acestea sunt indicii statice la clasele într-o altă clasă. După ce atribuiți un pointer, puteți apela funcții / metode din această clasă. Prin urmare, unele funcții de clasă sunt „delegate“ (In lumea C ++ - pointer la un pointer catre obiect de clasă) la o altă clasă.

Care sunt protocoale? Conceptual servește scopului ca fiind similar ca la fișierul de antet al clasei pe care atribuirea ca o clasă delegat. Un protocol este un mod explicit de a defini ceea ce trebuie să fie puse în aplicare în clasa care este indicatorul a fost stabilit ca un delegat în cadrul unei metode de clasă.

Cum pot face ceva similar în C ++? Dacă ați încercat să faceți acest lucru în C ++, v-ar prin definirea pointeri la clase (obiecte) în definiția clasei și apoi cablarea-le la alte clase care vor oferi funcții suplimentare ca delegați clasa de bază. Dar acest lucru de cabluri trebuie să fie maitained în codul și va fi lipsit de tact, și predispuse la erori. Obiectiv C doar presupune că programatorii cel mai bine nu sunt la menținerea acestei decipline și prevede restricții de compilator pentru a pune în aplicare o punere în aplicare curat.

Publicat 19/06/2013 la 11:34
sursa de către utilizator

voturi
9

versiune Swift

Un delegat este doar o clasa care face ceva pentru o altă clasă. Citiți următorul cod pentru o oarecum prostie (dar sperăm că edificator), de exemplu, Teren de joacă, care arată modul în care acest lucru se face în Swift.

// 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!"
}

În practica actuală, delegații sunt adesea folosite în următoarele situații

  1. Atunci când o clasă trebuie să comunice anumite informații către o altă clasă
  2. Atunci când o clasă dorește să permită o altă clasă să-l personalizați

Clasele nu trebuie să știe nimic despre unul pe altul în prealabil, cu excepția faptului că clasa delegat este conform protocolului necesar.

Am foarte recomandăm să citiți următoarele două articole. Ei ma ajutat să înțeleg delegați chiar mai bine decât documentația de făcut.

Publicat 05/11/2015 la 17:11
sursa de către utilizator

voturi
8

vă permite să presupunem că aveți o clasă pe care ați dezvoltat și doriți să declare o proprietate delegat pentru a fi capabil să-l anunțe atunci când se întâmplă un eveniment:

@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

astfel încât să declare un protocol în MyClassfișier antet (sau un fișier antet separat), și declară necesare Stivuitoare eveniment / opționale care delegatul trebuie / ar trebui să pună în aplicare, apoi declară o proprietate în MyClassde tip ( id< MyClassDelegate>) , ceea ce înseamnă orice clasă obiectiv C , care se conformează protocolul MyClassDelegate, veți observa că proprietatea delegat este declarat ca fiind slab, acest lucru este foarte important pentru a preveni și păstreze ciclu (cel mai adesea delegatul reține MyClassinstanța , deci , dacă ați declarat delegatul ca păstrează, ambele își vor păstra reciproc și nici dintre ei va fi vreodată eliberat).

veți observa , de asemenea , că metodele de protocol trece MyClassinstanța delegatului ca parametru, acest lucru este cea mai bună practică în cazul în care delegatul doriți să apelați unele metode pe MyClassinstanță și ajută , de asemenea , atunci când delegatul se declară ca MyClassDelegatela mai multe MyClasscazuri, cum ar fi atunci când aveți mai multe UITableView'scazuri în dumneavoastră ViewControllerși se declară ca UITableViewDelegatela toate acestea.

și în interiorul dumneavoastră MyClassvă va notifica delegatului cu evenimente declarate după cum urmează:

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

verificați mai întâi dacă delegatul răspunde la metoda de protocol pe care sunt pe cale de a apela în cazul în care delegatul nu-l pună în aplicare și aplicația se va prăbuși apoi (chiar dacă este necesară metoda de protocol).

Publicat 08/04/2015 la 13:24
sursa de către utilizator

voturi
8

Ok, acest lucru nu este cu adevărat un răspuns la întrebarea, dar dacă sunteți în căutarea în sus modul de a face propriul dvs. delegat poate ceva mult mai simplu ar putea fi un răspuns mai bun pentru tine.

Eu cu greu să pună în aplicare de delegați mei, pentru că am nevoie foarte rar. Eu pot avea doar un singur delegat pentru un obiect delegat. Deci, dacă doriți delegatul pentru un singur mod de comunicare / date care trece decât tine sunt mult mai bine de notificări.

NSNotification poate trece obiecte la mai mult de un destinatari și este foarte ușor de utilizat. Funcționează așa:

fișier MyClass.m ar trebui să arate așa

#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

Pentru a utiliza notificarea în alte clase: clasa Adăugați în calitate de observator:

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

Punerea în aplicare a selectorului:

- (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
}

Nu uitați să eliminați clasa ta în calitate de observator, dacă

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
Publicat 17/07/2013 la 05:58
sursa de către utilizator

voturi
6

Aici este o metodă simplă de a crea delegați

Creați protocol în fișierul .h. Asigurați-vă că este definită înainte de protocolul folosind @class urmată de numele UIViewController< As the protocol I am going to use is UIViewController class>.

Pasul: 1: Crearea unui nou protocol de clasă numit „YourViewController“ , care va fi subclasa de clasa UIViewController și atribuie această clasă la a doua ViewController.

Pasul: 2: Du - te la fișierul „YourViewController“ și modificați - l ca de mai jos:

#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

Metodele definite în comportamentul de protocol poate fi controlat cu @optional și @required ca parte a definiției protocolului.

Pasul: 3: Implementarea Delegat

    #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

// testa dacă metoda a fost definită înainte de a apela

 - (void) someMethodToCallDelegate {
     if ([[self delegate] respondsToSelector:@selector(defineDelegateMethodName:)]) {
           [self.delegate delegateMethodName:self]; 
     }
  }
Publicat 29/09/2015 la 09:23
sursa de către utilizator

voturi
5

Pentru a crea propriul delegat, mai întâi trebuie să creați un protocol și declară metodele necesare, fără punere în aplicare. Și apoi punerea în aplicare a acestui protocol în clasa antet în cazul în care doriți să pună în aplicare delegatului sau delegatul metode.

Un protocol trebuie declarat ca mai jos:

@protocol ServiceResponceDelegate <NSObject>

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

@end

Aceasta este clasa de serviciu în cazul în care ar trebui să se facă o anumită sarcină. Ea arată cum să se definească delegat și cum să setați delegatului. În clasa de punere în aplicare după ce sarcina este finalizată delegatului metodele sunt numite.

@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

Aceasta este principala clasa de vedere de unde clasa de serviciu este numit prin setarea delegat pentru sine. Și, de asemenea, protocolul este pus în aplicare în clasa antet.

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

- (void) go;

@end

@implementation viewController

//
//some methods
//

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

Asta e, și prin punerea în aplicare a metodelor delegatului din această clasă, de control va reveni odată ce operațiunea / sarcina se face.

Publicat 03/08/2015 la 04:47
sursa de către utilizator

voturi
1

Disclaimer: aceasta este Swiftversiunea a modului de a crea o delegate.

Deci, ce sunt delegați? ... în dezvoltarea de software, există arhitecturi generale de soluții reutilizabile, care ajuta la rezolvarea problemelor care apar în mod obișnuit într-un context dat, aceste „template-uri“, ca să spunem așa, sunt cel mai bine cunoscut sub numele de modele de design. Delegații sunt un model de design, care permite un obiect pentru a trimite mesaje de la un alt obiect atunci când se întâmplă un anumit eveniment. Imaginați-vă un obiect A apelează un obiect B pentru a efectua o acțiune. Odată ce acțiunea este finalizată, obiectul A ar trebui să știe că B a finalizat sarcina și să ia măsurile necesare, acest lucru poate fi realizat cu ajutorul delegaților!

Pentru o explicație mai bună, am de gând să - ți arăt cum să creați un delegat personalizat , care trece de date între clase, cu Swift într - o aplicație simplă, începe prin descărcarea sau clonarea acestui proiect de pornire și rulați - l!

Puteți vedea o aplicație cu două clase, ViewController Ași ViewController B. B are două puncte de vedere că la robinet schimbă culoarea de fundal a ViewController, nimic drept prea complicat? Ei bine , acum să ne gândim într - un mod ușor de a schimba , de asemenea , culoarea de fundal a clasa A , atunci când sunt lovit punctele de vedere cu privire la clasa B.

Problema este că acest puncte de vedere fac parte din clasa B și nu au nici o idee despre clasa A, așa că trebuie să găsim o modalitate de a comunica între aceste două clase, și asta în cazul în care delegare strălucește. Am împărțit punerea în aplicare în 6 etape, astfel încât să puteți folosi acest lucru ca o foaie de ieftin atunci când aveți nevoie.

Pasul 1: Căutați etapa marca pragma 1 în fișierul ClassBVC și adăugați

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

Primul pas este de a crea o protocol, în acest caz, vom crea protocolul în clasa B, în interiorul protocolul puteți crea cât mai multe funcții pe care le doriți , în funcție de cerințele de punere în aplicare dumneavoastră. În acest caz, avem doar o singură funcție simplă , care acceptă un opțional UIColorca argument. Este o bună practică pentru a denumi protocoalele adăugând cuvântul delegatela sfârșitul numelui de clasă, în acest caz, ClassBVCDelegate.

Pasul 2: Uita - te pentru etapa marca pragma 2 în ClassVBCși adăugați

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

Aici vom crea doar o proprietate delegat pentru clasa, această proprietate trebuie să adopte protocoltipul, și ar trebui să fie opțională. De asemenea, ar trebui să adăugați cuvântul cheie slab înainte de proprietate , pentru a evita să păstreze ciclurile și potențiale pierderi de memorie, dacă nu știi ce înseamnă să nu vă faceți griji pentru moment, doar amintiți - vă pentru a adăuga acest cuvânt cheie.

pasul 3: Uita - te pentru pasul marca pragma 3 în interiorul handleTap methodîn ClassBVCși adăugați

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

Un lucru pe care ar trebui să știți, rulați aplicația și apăsați pe orice punct de vedere, nu veți vedea nici un comportament nou și că este corect , dar lucrul pe care vreau să subliniez este faptul că aplicația nu este crashing atunci când delegatul este numit și este pentru că am crea ca valoare opțională și de aceea nu se va prăbuși Chiar și faptul delegat nu există încă. Să mergem acum la ClassAVCdosar și să - l, delegate.

Pasul 4: Uita - te pentru etapa marca pragma 4 în interiorul metodei handleTap în ClassAVCși adăugați lângă tipul de clasă ca aceasta.

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

Acum ClassAVC a adoptat ClassBVCDelegateprotocolul, puteți vedea că dvs. compilator este oferindu - vă o eroare care spune „ de tip„ClassAVC nu este conform cu protocolul «ClassBVCDelegate» , iar acest lucru înseamnă numai că nu a folosit metodele protocolul încă, imaginați - vă că când clasa a adoptă protocolul este ca semnarea unui contract cu clasa B și acest contract spune : „Orice clasă de adoptare trebuie să - mi folosesc funcțiile mele!“

Notă rapidă: Dacă veniți dintr - un Objective-Cfond pe care , probabil , gândindu - mă că vă puteți închide de asemenea, această eroare a face această metodă opțională, dar pentru surprinderea mea, și , probabil , a ta, Swiftlimba nu acceptă opțional protocols, dacă doriți să - l faci , puteți crea o extensie pentru dvs. protocolsau de a folosi cuvântul cheie @objc în dvs. de protocolpunere în aplicare.

Personal, Dacă am de a crea un protocol cu metode diferite opționale , aș prefera să - l rupe în diferite protocols, în acest fel voi urmări conceptul de a da o singură responsabilitate pentru obiectele mele, dar poate varia în funcție de punerea în aplicare specifice.

aici este un articol bun despre metodele opționale.

Pasul 5: Uita-te pentru etapa de marca pragma 5 interiorul prepara pentru metoda Segue și adăugați

//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
}

Aici vom crea doar o instanță a ClassBVCși atribui delegatului său de sine, dar ceea ce este de la sine aici? bine, de sine este , ClassAVCcare a fost delegată!

Pasul 6: În cele din urmă, uita - te pentru etapa pragma 6 în ClassAVCși să folosească funcțiile de protocol, începe să tastați FUNC changeBackgroundColor și veți vedea că este auto-completare pentru tine. Puteți adăuga orice implementare în interiorul acestuia, în acest exemplu, vom schimba doar culoarea de fundal, adăugați acest lucru.

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

Acum, rulați aplicația!

Delegatessunt peste tot si tu , probabil , le utilizați fără a observa chiar, dacă creați o tableviewîn trecut ați folosit de delegare, in mai multe clase de UIKITlucrări în jurul lor și multe alte frameworksasemenea, ei rezolva aceste probleme principale.

  • Evitați cuplarea etanșă a obiectelor.
  • Modifică comportamentul și aspectul fără a fi nevoie de a subclasa obiecte.
  • Permite îndeplinirea sarcinilor care urmează să fie manipulate în afara oricărui obiect arbitrar.

Felicitări, ați pune în aplicare doar un delegat personalizat, eu știu că sunt , probabil , de gândire, probleme atât de mult doar pentru asta? bine, delegarea este un model de design foarte important pentru a înțelege dacă doriți să devină un iOSdezvoltator, și să păstreze întotdeauna în vedere faptul că acestea au un la o relație între obiecte.

Puteti vedea tutorialul original , aici

Publicat 26/04/2017 la 05:27
sursa de către utilizator

voturi
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;

Metodă:

-(void)delegateMEthod: (ArgType) arg{
}
Publicat 19/12/2016 la 04:14
sursa de către utilizator

voturi
0

Raspuns este, de fapt a răspuns, dar aș dori să vă dau o „foaie de ieftin“ pentru a crea un delegat:

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
Publicat 16/03/2018 la 04:40
sursa de către utilizator

voturi
0

Să începem cu un exemplu, dacă cumpărăm un produs on-line, acesta trece printr-un proces cum ar fi de transport maritim / livrare gestionate de diferite teams.So în cazul în care de transport maritim devine finalizat, echipa de transport maritim ar trebui să notifice echipa de livrare și ar trebui să fie una la o comunicare ca difuzare aceste informații ar fi deasupra capului pentru alte persoane / furnizor ar putea dori să treacă aceste informații numai persoanelor necesare.

Deci, dacă ne gândim în termeni de aplicația noastră, un eveniment poate fi o comanda online si echipe diferite pot fi ca mai multe vizualizări.

Aici este codul ia in considerare ShippingView ca echipa Transport & DeliveryView ca echipa de livrare:

//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
        //
    }
}
Publicat 14/07/2017 la 10:14
sursa de către utilizator

voturi
0

La punctul meu de vedere a crea clasă separată pentru metoda delegat și puteți folosi în cazul în care doriți.

în meu de 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;

după acel fișier in.m crea matrice cu obiecte,

 - (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];
        }
    }
}];
}

Aici toate sunt stabilite pentru personalizat delegat class.after pe care o puteți utiliza această metodă în cazul în care ați delegat want.for exemplu ...

în altă mea de import viewcontroller după aceea

a crea o acțiune pentru apelarea metodei delegat ca aceasta

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

după această metodă de apel delegat ca aceasta

- (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;
}
}
Publicat 08/02/2017 la 09:30
sursa de către utilizator

voturi
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. Punerea în aplicare a metodei în .m clasei - (void) didRemoveCellWithTag: (NSInteger) tag-ul {NSLog @ ( "tag% d", tag);

}

Publicat 02/01/2017 la 16:31
sursa de către utilizator

voturi
0

Delegați: - Crearea

@protocol addToCartDelegate <NSObject>

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

@end

Trimite și atribuiți delegat pentru a vizualiza trimiteți date

[self.delegate addToCartAction:itemsModel isAdded:YES];
Publicat 08/12/2016 la 10:50
sursa de către utilizator

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