Come faccio a creare i delegati in Objective-C?

voti
683

So come funzionano i delegati, e so come io possa usare.

Ma come faccio a creare loro?

È pubblicato 09/03/2009 alle 17:06
fonte dall'utente
In altre lingue...                            


19 risposte

voti
852

Un delegato di Objective-C è un oggetto che è stato assegnato alla delegateproprietà un altro oggetto. Per crearne uno, è sufficiente definire una classe che implementa i metodi delegato che ti interessa, e contrassegnare la classe come l'attuazione del protocollo di delegato.

Ad esempio, supponiamo di avere un UIWebView. Se desideri implementare dei suoi delegati webViewDidStartLoad:metodo, è possibile creare una classe come questa:

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

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

Poi si potrebbe creare un'istanza di MyClass e assegnarla come delegato della vista web:

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

Sul UIWebViewlato, probabilmente ha un codice simile a questo per vedere se il delegato risponde al webViewDidStartLoad:messaggio utilizzando respondsToSelector:e inviarlo, se del caso.

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

La struttura delegato sé è tipicamente dichiarata weak(ARC) o assign(pre-ARC) per evitare trattenere loop, poiché il delegato di un oggetto spesso contiene un forte riferimento a tale oggetto. (Ad esempio, un controller di vista è spesso il delegato di una vista che contiene.)

Fare delegati per le classi

Per definire i propri delegati, si dovrà dichiarare i loro metodi da qualche parte, come discusso nella Mela Documenti sui protocolli . Di solito si dichiara un protocollo formale. La dichiarazione, parafrasato da UIWebView.h, sarebbe simile a questa:

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

Questo è analogo a un'interfaccia o classe astratta di base, in quanto crea un tipo speciale per il vostro delegato, UIWebViewDelegatein questo caso. Implementatori delegato dovrebbe adottare questo protocollo:

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

E poi implementare i metodi del protocollo. Per i metodi dichiarati nel protocollo come @optional(come la maggior parte dei metodi delegato), è necessario controllare con -respondsToSelector:prima di chiamare un particolare metodo su di esso.

Naming

Metodi delegato sono in genere chiamati a cominciare dal nome della classe delegante, e prendere l'oggetto delegante come primo parametro. Essi hanno inoltre spesso usano una forma volontà-, dovresti- o did-. Così, webViewDidStartLoad:(primo parametro è la visualizzazione Web) invece di loadStarted(prendendo senza parametri) per esempio.

Le ottimizzazioni di velocità

Invece di verificare se un delegato risponde a un selettore ogni volta che vogliamo al messaggio, è possibile memorizzare nella cache le informazioni quando sono impostati i delegati. Un modo molto pulito per farlo è quello di utilizzare un campo di bit, come segue:

@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

Poi, nel corpo, siamo in grado di verificare che il nostro delegato gestisce i messaggi accedendo al nostro delegateRespondsTostruct, piuttosto che con l'invio di -respondsToSelector:più e più volte.

I delegati informali

Prima di protocolli esistevano, era comune l'uso di un categoria su NSObjectdi dichiarare i metodi di un delegato potrebbe implementare. Ad esempio, CALayerlo fa ancora questo:

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

Questo dice in sostanza il compilatore che qualsiasi oggetto può implementare displayLayer:.

Si potrebbe quindi utilizzare lo stesso -respondsToSelector:metodo come descritto sopra per chiamare questo metodo. I delegati semplicemente implementare questo metodo e assegnare la delegateproprietà, e il gioco è fatto (non c'è dichiarando si conformi ad un protocollo). Questo metodo è comune nelle biblioteche di Apple, ma il nuovo codice dovrebbe utilizzare il più moderno approccio protocollo di cui sopra, in quanto tale impostazione inquina NSObject(che rende autocomplete meno utile) e rende difficile per il compilatore mettere in guardia su errori di battitura e simili.

Risposto il 09/03/2009 a 17:16
fonte dall'utente

voti
360

La risposta approvata è grande, ma se siete alla ricerca di una risposta 1 minuto provare questo:

MyClass.h file dovrebbe essere simile a questo (aggiungere linee delegato con i commenti!)

#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

file di MyClass.m dovrebbe assomigliare a questo

#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

Per utilizzare il delegato in un'altra classe (UIViewController chiamato MyVC in questo caso) 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

Implementare metodo delegato

- (void) myClassDelegateMethod: (MyClass *) sender {
    NSLog(@"Delegates are great!");
}
Risposto il 30/09/2012 a 11:25
fonte dall'utente

voti
18

Quando si utilizza il metodo di protocollo formale per la creazione di supporto delegato, ho scoperto che è possibile garantire il corretto tipo di controllo (anche se, tempo di esecuzione, non compilazione di tempo) con l'aggiunta di qualcosa di simile a:

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

nel codice di accesso delegato (setDelegate). Questo aiuta a ridurre al minimo gli errori.

Risposto il 04/05/2010 a 21:42
fonte dall'utente

voti
17

Forse questo è più lungo le linee di che cosa ti manca:

Se si proviene da un punto di vista C ++ come, delegati prende un po 'per abituarsi - ma in fondo 'che solo di lavoro'.

Il modo in cui funziona è che si imposta un oggetto che hai scritto come delegato al NSWindow, ma il vostro oggetto ha solo implementazioni (metodi) per uno o alcuni dei molti metodi delegato possibili. Così succede qualcosa, e NSWindowvuole chiamare l'oggetto - è solo utilizza di Objective-C respondsToSelectormetodo per determinare se l'oggetto vuole che il metodo chiamato, e poi lo chiama. Questo è come funziona Objective-C - metodi vengono ricercati su richiesta.

E 'del tutto banale di fare questo con i propri oggetti, non c'è niente di speciale in corso, si potrebbe per esempio avere una NSArraydi 27 oggetti, tutti i diversi tipi di oggetti, solo il 18 per alcuni di loro che hanno il metodo -(void)setToBue;Gli altri 9 non fare. Quindi, per chiamare setToBluein tutto 18 che ne hanno bisogno fatto, qualcosa di simile a questo:

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

L'altra cosa su delegati è che essi non sono conservati, in modo da avere sempre impostare il delegato per nilnel vostro MyClass deallocmetodo.

Risposto il 10/03/2009 a 01:18
fonte dall'utente

voti
16

Per favore! controllare sotto semplice passo a passo per capire come funziona delegati in iOS.

Delegato in iOS

Ho creato due ViewControllers (per l'invio di dati da uno all'altro)

  1. FirstViewController attuare delegato (che fornisce dati).
  2. SecondViewController dichiarare il delegato (che riceverà i dati).
Risposto il 27/02/2013 a 13:21
fonte dall'utente

voti
15

Come una buona pratica raccomandata da Apple, è un bene per il delegato (che è un protocollo, per definizione), di conformarsi alle NSObjectprotocollo.

@protocol MyDelegate <NSObject>
    ...
@end

E per creare metodi opzionali all'interno del vostro delegato (vale a dire metodi che non devono necessariamente essere implementata), è possibile utilizzare l' @optionalannotazione in questo modo:

@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

Così, quando si utilizzano i metodi che avete specificato come optional, è necessario (in classe) verificare con respondsToSelectorse la vista (che è conforme al vostro delegato) ha effettivamente implementato il metodo opzionale (s) o meno.

Risposto il 04/08/2013 a 09:39
fonte dall'utente

voti
10

Credo che tutte queste risposte fanno un sacco di senso una volta capito delegati. Personalmente mi è venuto dalla terra di C / C ++ e prima che i linguaggi procedurali come Fortran, ecc: ecco i miei 2 min assumono trovare analoghi simili nel paradigma C ++.

Se dovessi spiegare ai delegati di un programmatore C ++ / Java direi

Quali sono i delegati? Questi sono i puntatori statici a classi all'interno di un'altra classe. Una volta che si assegna un puntatore, è possibile chiamare funzioni / metodi in quella classe. Da qui alcune funzioni della vostra classe sono "delegati" (Nel mondo C ++ - puntatore a da un puntatore oggetto di classe) ad un'altra classe.

Quali sono i protocolli? Concettualmente serve scopo il più simile al file di intestazione della classe si sta assegnando come classe delegato. Un protocollo è un modo esplicito di definire ciò che deve essere implementato nella classe che è puntatore è stato impostato come un delegato all'interno di una classe metodi.

Come posso fare qualcosa di simile in C ++? Se si è tentato di fare questo in C ++, si sarebbe definendo puntatori a classi (oggetti) nella definizione della classe e poi li cablaggio fino ad altre classi che forniranno funzioni aggiuntive come delegati alla vostra classe di base. Ma questo cablaggio deve essere maitained all'interno del codice e sarà goffo e soggetto a errori. Objective C presuppone solo che i programmatori non sono meglio a mantenere questo decipline e fornisce restrizioni compilatore per imporre un'implementazione pulita.

Risposto il 19/06/2013 a 11:34
fonte dall'utente

voti
9

versione Swift

Un delegato è solo una classe che fa un certo lavoro per un'altra classe. Leggere il seguente codice per un po 'stupida (ma si spera illuminante) esempio giochi che mostra come questo viene fatto in 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!"
}

In pratica, i delegati sono spesso utilizzati nelle seguenti situazioni

  1. Quando una classe ha bisogno di comunicare alcune informazioni per un'altra classe
  2. Quando una classe vuole permettere un'altra classe personalizzarlo

Le classi non hanno bisogno di sapere nulla l'uno dell'altro in anticipo, tranne che la classe delegato conforme al protocollo richiesto.

Mi raccomando di leggere i seguenti due articoli. Mi hanno aiutato a capire i delegati anche meglio di documentazione di fatto.

Risposto il 05/11/2015 a 17:11
fonte dall'utente

voti
8

supponiamo di avere una classe che avete sviluppato e desidera dichiarare una proprietà delegato per essere in grado di notificare quando un certo evento si verifica:

@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

così si dichiara un protocollo nel MyClassfile di intestazione (o un file di intestazione separata), e dichiarare i gestori di eventi richiesti / opzionali che il delegato deve / dovrebbe implementare, quindi dichiarare una proprietà in MyClassdi tipo ( id< MyClassDelegate>) il che significa che tutte le classi Objective C che è conforme a il protocollo MyClassDelegate, si noterà che la proprietà delegato è dichiarato come debole, questo è molto importante per evitare mantenere ciclo (il più delle volte il delegato mantiene l' MyClassistanza in modo, se avete dichiarato il delegato come conservare, ciascuno di essi manterrà l'altro e nessuno di loro potrà mai essere rilasciato).

si noterà anche che i metodi di protocollo passa l' MyClassistanza al delegato come parametro, questo è delle migliori pratiche nel caso in cui il delegato desidera chiamare alcuni metodi di MyClassistanza e aiuta anche quando il delegato si dichiara come MyClassDelegatea più MyClassistanze, come quando si dispone di più UITableView'sle istanze nel vostro ViewControllere si dichiara come UITableViewDelegatea tutti loro.

e dentro il vostro MyClasssi comunica il delegato con gli eventi dichiarati come segue:

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

in primo luogo verificare se il delegato risponde al metodo di protocollo che si sta per chiamare in caso il delegato non applicarla e l'applicazione va in crash allora (anche se è richiesto il metodo di protocollo).

Risposto il 08/04/2015 a 13:24
fonte dall'utente

voti
8

Ok, questo non è davvero una risposta alla domanda, ma se si sta cercando il modo per rendere il proprio delegato forse qualcosa molto più semplice potrebbe essere una risposta migliore per voi.

Quasi non implementare miei delegati perchè raramente bisogno. Posso avere un solo delegato per un oggetto delegato. Quindi, se si desidera che il delegato per una comunicazione via / il passaggio di dati di quello che sei molto meglio di con le notifiche.

NSNotification può passare oggetti a più destinatari ed è molto facile da usare. Funziona in questo modo:

file di MyClass.m dovrebbe assomigliare a questo

#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

Per utilizzare la notifica in un altro classi: Aggiungi classe in qualità di osservatore:

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

Attuare il selettore:

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

Non dimenticare di rimuovere la classe in qualità di osservatore, se

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
Risposto il 17/07/2013 a 05:58
fonte dall'utente

voti
6

Ecco un metodo semplice per creare i delegati

Creare protocollo file h. Assicurarsi che sia definita prima che il protocollo utilizzando @class seguito dal nome della UIViewController< As the protocol I am going to use is UIViewController class>.

Passo 1: Creare un nuovo protocollo classe denominata "YourViewController", che sarà la sottoclasse di UIViewController e assegnare questa classe per il secondo ViewController.

Passo: 2: Vai alla scheda "YourViewController" e modificarlo come di seguito:

#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

I metodi definiti nel protocollo di comportamento possono essere controllate con @optional e @required come parte della definizione del protocollo.

Fase: 3: Attuazione delle Delegate

    #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

// verificare se il metodo è stato definito prima di chiamare

 - (void) someMethodToCallDelegate {
     if ([[self delegate] respondsToSelector:@selector(defineDelegateMethodName:)]) {
           [self.delegate delegateMethodName:self]; 
     }
  }
Risposto il 29/09/2015 a 09:23
fonte dall'utente

voti
5

Per creare la tua delegato, in primo luogo è necessario creare un protocollo e dichiarare i metodi necessari, senza implementare. E quindi implementare questo protocollo nella tua classe di intestazione in cui si desidera implementare i metodi delegato o delegare.

Un protocollo deve essere dichiarato come di seguito:

@protocol ServiceResponceDelegate <NSObject>

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

@end

Questa è la classe di servizio in cui dovrebbe essere fatto qualche compito. Essa mostra come definire delegato e come impostare il delegato. Nella classe di implementazione dopo l'operazione è completata del delegato i metodi sono chiamati.

@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

Questa è la classe di visualizzazione principale da dove la classe di servizio si chiama impostando il delegato a se stesso. E anche il protocollo è implementato nella classe di intestazione.

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

- (void) go;

@end

@implementation viewController

//
//some methods
//

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

Questo è tutto, e mediante l'attuazione di metodi delegato in questa classe, il controllo tornerà una volta che l'operazione / compito è fatto.

Risposto il 03/08/2015 a 04:47
fonte dall'utente

voti
1

Diniego: questa è la Swiftversione di come creare un delegate.

Allora, quali sono i delegati? ... nello sviluppo di software, ci sono le architetture di soluzioni riutilizzabili generali che aiutano a risolvere i problemi che si verificano comunemente all'interno di un determinato contesto, questi “modelli”, per così dire, sono meglio conosciuti come i design pattern. I delegati sono un modello di progettazione che consente a un oggetto di inviare messaggi a un altro oggetto quando un evento specifico accade. Immaginate un oggetto A chiama un oggetto B per eseguire un'azione. Una volta che l'azione è completa, l'oggetto A dovrebbe sapere che B ha completato il compito e prendere le azioni necessarie, questo può essere realizzato con l'aiuto dei delegati!

Per una spiegazione migliore, sto per mostrarvi come creare un delegato personalizzato che passa i dati tra le classi, con Swift in una semplice applicazione, inizia scaricando o la clonazione questo progetto di avviamento ed eseguirlo!

Si può vedere un app con due classi, ViewController Ae ViewController B. B ha due punti di vista che alla spina cambia il colore dello sfondo ViewController, niente di troppo complicato giusto? Bene, ora pensiamo in un modo semplice per cambiare anche il colore di sfondo di classe A quando il punto di vista di classe B sono sotto controllo.

Il problema è che questa vista sono parte della classe B e non hanno alcuna idea di classe A, quindi abbiamo bisogno di trovare un modo per comunicare tra queste due classi, ed è lì che la delega brilla. Ho diviso la realizzazione in 6 punti in modo da poter utilizzare questo come un foglietto quando ne avete bisogno.

Fase 1: Cercare il punto marchio pragma 1 nel file ClassBVC e aggiungere questo

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

Il primo passo è quello di creare una protocol, in questo caso, creeremo il protocollo in classe B, all'interno del protocollo è possibile creare il maggior numero di funzioni che si desidera in base ai requisiti della propria implementazione. In questo caso, abbiamo solo una semplice funzione che accetta un optional UIColorcome argomento. È una buona pratica per denominare i protocolli aggiungendo la parola delegatealla fine del nome della classe, in questo caso, ClassBVCDelegate.

Fase 2: Cercare il passo marchio pragma 2 in ClassVBCe aggiungere questo

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

Qui ci limitiamo a creare una proprietà delegato per la classe, questa proprietà deve adottare il protocoltipo, e dovrebbe essere facoltativo. Inoltre, si dovrebbe aggiungere la parola chiave deboli prima che la proprietà per evitare mantenere cicli e potenziali perdite di memoria, se non si sa che cosa significa non ti preoccupare, per ora, basta ricordarsi di aggiungere questa parola chiave.

Fase 3: Cercare il punto marchio pragma 3 all'interno del handleTap methodin ClassBVCe aggiungere questo

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

Una cosa che si dovrebbe sapere, eseguire l'applicazione e toccare in ogni caso, non sarà possibile visualizzare alcun nuovo comportamento e questo è corretto, ma la cosa che voglio sottolineare è che l'applicazione non è crash quando il delegato è chiamato, e è perché creiamo come un valore facoltativo ed è per questo che non vada in crash anche il delegato non esiste ancora. Vediamo ora per ClassAVCarchiviare e rendere, il delegato.

Passo 4: Cercare il passo marchio pragma 4 all'interno del metodo handleTap in ClassAVCe aggiungere questo accanto al tipo di classe come questa.

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

Ora ClassAVC ha adottato il ClassBVCDelegateprotocollo, si può vedere che il compilatore ti dà un errore che dice “Tipo 'ClassAVC non è conforme al protocollo 'ClassBVCDelegate' e questo significa solo che non è stato utilizzato i metodi del protocollo ancora, immaginate che quando la classe a adotta il protocollo è come firmare un contratto con la classe B e questo contratto dice “Ogni classe adottando mi devono utilizzare le mie funzioni!”

Breve nota: Se si proviene da un Objective-Cfondo probabilmente state pensando che si può anche stare zitto che l'errore fare quel metodo facoltativo, ma per la mia sorpresa, e, probabilmente, la tua, Swiftla lingua non supporta opzionale protocols, se si vuole farlo è possibile creare un'estensione per il vostro protocolo di utilizzare la parola chiave @objc nella vostra protocolimplementazione.

Personalmente, se devo creare un protocollo con diversi metodi opzionali preferirei spezzare in diverso protocols, in questo modo io seguirò il concetto di dare una sola responsabilità verso i miei oggetti, ma può variare in base alla specifica implementazione.

qui è un buon articolo sui metodi opzionali.

Passo 5: Cercare il punto marchio pragma 5 all'interno della preparazione per il metodo segue e aggiungere questo

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

Qui ci sono solo la creazione di un'istanza di ClassBVCe assegnare suo delegato per sé, ma ciò che è auto qui? bene, l'auto è il ClassAVC, che è stato delegato!

Fase 6: Infine, cercare la fase pragma 6 ClassAVCe usiamo le funzioni del protocol, iniziare a digitare func changeBackgroundColor e vedrete che si tratta di auto-completamento per voi. È possibile aggiungere qualsiasi applicazione al suo interno, in questo esempio, ci sarà solo cambiare il colore di sfondo, aggiungere questo.

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

Ora eseguire l'applicazione!

Delegatessono ovunque e probabilmente li usa senza nemmeno accorgersene, se si crea un tableviewin passato è stato utilizzato di delega, le molte classi di UIKITopere intorno a loro e molti altri frameworksanche, risolvono questi problemi principali.

  • Evitare stretto accoppiamento di oggetti.
  • Modificare il comportamento e l'aspetto senza la necessità di creare una sottoclasse oggetti.
  • Dei compiti che ad essere gestite via a qualsiasi oggetto arbitrario.

Congratulazioni, basta implementare un delegato personalizzato, so che probabilmente stai pensando, così tanti problemi solo per questo? bene, la delega è un modello di progettazione molto importante capire se si vuole diventare uno iOSsviluppatore, e tenere sempre a mente che non hanno relazione uno a uno tra gli oggetti.

Potete vedere il tutorial originale qui

Risposto il 26/04/2017 a 05:27
fonte dall'utente

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

Metodo:

-(void)delegateMEthod: (ArgType) arg{
}
Risposto il 19/12/2016 a 04:14
fonte dall'utente

voti
0

Risposta è in realtà risposto, ma vorrei darvi un "cheat sheet" per la creazione di un delegato:

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
Risposto il 16/03/2018 a 04:40
fonte dall'utente

voti
0

Cominciamo con un esempio, se compriamo un prodotto online, passa attraverso processi come la spedizione / consegna gestito da diversi teams.So se il trasporto viene completato, la squadra di trasporto dovrebbe notificare squadra di consegna e dovrebbe essere 1-1 comunicazione come broadcasting queste informazioni sarebbe in testa per le altre persone / fornitore potrebbe desiderare di passare queste informazioni solo a persone richieste.

Quindi, se pensiamo in termini di nostra applicazione, un evento può essere un ordine online e diverse squadre può essere come viste multiple.

Ecco il codice considerano ShippingView come squadra Spedizioni e DeliveryView come squadra di consegna:

//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
        //
    }
}
Risposto il 14/07/2017 a 10:14
fonte dall'utente

voti
0

Nel mio punto di vista di creare classe separata per questo metodo delegato ed è possibile utilizzare dove si vuole.

nel mio DropDownClass.h personalizzato

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;

dopo di che il file in.m creare array con gli oggetti,

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

Qui tutti sono fissati per Custom class.after delegato che è possibile utilizzare questo metodo delegato dove want.for esempio ...

nel mio un'altra importazione viewcontroller dopo che

creare azione per chiamare metodo delegato come questo

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

dopo quella chiamata di metodo delegato come questo

- (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;
}
}
Risposto il 08/02/2017 a 09:30
fonte dall'utente

voti
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. Implementare il metodo nella classe di .m - (void) didRemoveCellWithTag: (NSInteger) tag {NSLog @ ( "Tag% d", tag);

}

Risposto il 02/01/2017 a 16:31
fonte dall'utente

voti
0

Delegare: - Creare

@protocol addToCartDelegate <NSObject>

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

@end

Invia e vi prego di assegnare delegato per vedere che si sta inviando i dati

[self.delegate addToCartAction:itemsModel isAdded:YES];
Risposto il 08/12/2016 a 10:50
fonte dall'utente

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