Jak mohu vytvořit delegáty v Objective-C?

hlasů
683

Vím, jak delegáti pracují, a vím, jak jsem je používat.

Ale jak mohu vytvořit jim?

Položena 09/03/2009 v 17:06
zdroj uživatelem
V jiných jazycích...                            


19 odpovědí

hlasů
852

Objektivní-C delegát je objekt, který byl přidělen k delegatemajetku jiného objektu. Chcete-li vytvořit, jednoduše definovat třídu, která implementuje metody delegáta, které vás zajímají, a označit tuto třídu jako implementaci protokolu delegáta.

Předpokládejme například, že máte UIWebView. Pokud byste chtěli, aby provedla svůj delegáta webViewDidStartLoad:metodu, můžete vytvořit třídu, jako je tento:

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

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

Pak byste mohli vytvořit instanci Moje_třída a přiřadit ji jako delegát webového náhledu:

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

Na UIWebViewstraně, pravděpodobně to má kód podobný tomu, aby zjistili, zda delegát reaguje na webViewDidStartLoad:zprávy pomocí respondsToSelector:a případně poslat ji.

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

Vlastnost zástupce sám je typicky deklarován weak(ARC) nebo assign(předem ARC), aby se zabránilo udržet smyčky, protože zástupce objektu často má silný odkaz na tento objekt. (Například regulátor pohled je často zástupce ze zobrazení, které obsahuje.)

Tvorba delegáta na svých tříd

Definovat vlastní delegátů, budete muset deklarovat své metody někde, jak je popsáno v Apple Docs na protokolech . Obvykle prohlásit formální protokol. V prohlášení, parafrázoval z UIWebView.h, bude vypadat takto:

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

Toto je analogické s rozhraním nebo abstraktní základní třídy, neboť vytváří zvláštní druh vašeho delegáta, UIWebViewDelegatev tomto případě. Delegáta implementátoři bude muset přijmout tento protokol:

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

A pak implementovat metody v protokolu. Pro metody deklarované v protokolu as @optional(jako většina metod delegátů), je třeba se poradit se -respondsToSelector:před voláním konkrétní metodu na to.

pojmenování

Metody delegáta jsou obvykle pojmenovány počínaje názvem pověřil třídy a vzít objekt pověřil jako první parametr. Oni také často používají záměr předkládat, should- nebo did- formulář. Takže, webViewDidStartLoad:(první parametr je web view) spíše než loadStarted(s žádné parametry), např.

rychlostní optimalizace

Místo toho, aby kontroly, zda delegát reaguje na selektor pokaždé, když chceme, aby zprávy ji můžete mezipaměti tyto informace, pokud jsou nastaveny delegátů. Jedním z velmi čistý způsob, jak to udělat, je použít bitové pole, a to následovně:

@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

Pak, v těle, můžeme zjistit, že náš delegát zpracovává zprávy pomocí přístupu naší delegateRespondsTostruct, spíše než tím, že pošle -respondsToSelector:znovu a znovu.

neformální Delegáti

Než existovalo protokolů bylo běžné používat kategorii na NSObjectdeklarovat metody delegáta mohla realizovat. Například CALayerstále dělá toto:

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

To v podstatě říká kompilátoru, že nějaký objekt mohl realizovat displayLayer:.

Pak byste použít stejný -respondsToSelector:postup, jak je popsáno výše, aby volat tuto metodu. Delegáti jednoduše implementovat tuto metodu a přiřadit delegatevlastnost, a to je (není deklarovat vám vyhovovat protokolu). Tato metoda je běžné v Apple knihovnách, ale nový kód by měl používat modernější protokol přístupu výše, protože tento přístup znečišťuje NSObject(což autocomplete méně užitečné) a ztěžuje kompilátor vás varovat o překlepy a podobné chyby.

Odpovězeno 09/03/2009 v 17:16
zdroj uživatelem

hlasů
360

Schválený Odpověď je skvělé, ale pokud hledáte pro 1 minutu odpověď zkusit toto:

MyClass.h soubor by měl vypadat takto (přidat delegáta řádky s komentářem!)

#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 soubor by měl vypadat takto

#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

Chcete-li používat delegáta v jiné třídě (UIViewController volal MyVC v tomto případě) 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

Implementovat metodu delegáta

- (void) myClassDelegateMethod: (MyClass *) sender {
    NSLog(@"Delegates are great!");
}
Odpovězeno 30/09/2012 v 11:25
zdroj uživatelem

hlasů
18

Při použití metody formální protokol pro vytváření podpory delegáta, jsem zjistil, že si můžete zajistit správný typ kontroly (byť, běhu, není kompilaci) přidáním něco jako:

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

v kódu delegáta accessor (setDelegate). To pomáhá minimalizovat chyby.

Odpovězeno 04/05/2010 v 21:42
zdroj uživatelem

hlasů
17

Možná je to víc v duchu toho, co vám chybí:

Pokud jsou na cestě z C ++, jako pohledu, delegáti trvá trochu zvyknout - ale v podstatě ‚prostě fungovat‘.

Způsob, jakým to funguje tak, že si přejete nastavit nějaký objekt, který jste napsal jako delegát NSWindow, ale váš objekt má pouze implementace (metody) pro jeden nebo několik z mnoha možných způsobů delegáta. Takže co se stane, a NSWindowchce-li volat svou objekt - to prostě používá Objective-C je respondsToSelectormetoda pro určení, zda váš objekt chce tuto metodu zvanou, a volá ho. To je, jak Objective-C funguje - metody jsou vyhledávány na vyžádání.

Je naprosto triviální, jak to udělat na vlastní objekty, není nic zvláštního děje, můžete například mít NSArray27 objektů, všechny různé druhy objektů, pouze 18 z nichž některé mají metodu -(void)setToBue;Druhý 9 ne. Takže volat setToBluena všech 18, které je třeba to udělat, něco takového:

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

Další věc, o delegátů je, že nejsou zachovány, takže budete mít vždy nastavit delegát nilve své MyClass deallocmetodě.

Odpovězeno 10/03/2009 v 01:18
zdroj uživatelem

hlasů
16

Prosím! zkontrolujte jednoduchý krok za krokem tutoriál, aby pochopili, jak funguje Delegáti v iOS.

Delegát v iOS

Vytvořil jsem dvě ViewControllers (pro odesílání dat z jednoho do druhého)

  1. FirstViewController realizovat delegáta (který poskytuje data).
  2. SecondViewController prohlásit delegáta (který bude přijímat data).
Odpovězeno 27/02/2013 v 13:21
zdroj uživatelem

hlasů
15

Jako dobré praxe doporučené společností Apple, je to dobré pro delegáta (což je protokol, samozřejmě), aby v souladu s NSObjectprotokolem.

@protocol MyDelegate <NSObject>
    ...
@end

A vytvářet doplňkové metody v rámci vašeho delegáta (tj metod, které nemusí být nutně realizovány), můžete použít @optionalanotaci takto:

@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

Takže při použití metod, které jste zadali jako volitelný, je třeba (ve třídě), obraťte se respondsToSelectorv případě, že zobrazení (který je v souladu s vaší delegáta) skutečně realizovány vaše volitelná metoda (y), nebo ne.

Odpovězeno 04/08/2013 v 09:39
zdroj uživatelem

hlasů
10

Myslím, že všechny tyto odpovědi udělat hodně smysl, jakmile pochopíte delegátů. Osobně jsem přišel ze země C / C ++ a před tím procedurálních jazyků jako Fortran atd takže tady je moje 2 min vzít na hledání podobné analogy v jazyce C ++ paradigmatu.

Pokud bych měl vysvětlit, delegáty na C ++ / Java programátor řekl bych,

Jaké jsou delegáti? Jedná se o statické ukazatele na výuku v rámci jiné třídy. Jakmile přiřadíte ukazatel, můžete volat funkce / metody v této třídě. Z tohoto důvodu některé funkce vaší třídy jsou „v přenesené pravomoci“ (v jazyce C ++ světě - ukazatel ukazatelem je třída objektu) do jiné třídy.

Jaké jsou protokoly? Koncepčně slouží jako podobnému účelu, pokud jde o soubor záhlaví třídy, kterou se přiřazení jako třída delegáta. Protokol je explicitní způsob, jak definovat, co je třeba realizován ve třídě, kdo je ukazatel byl stanoven jako delegát v rámci třídy metody.

Jak mohu udělat něco podobného v C ++? Pokud jste se snažil udělat v C ++ byste definováním ukazatele na třídy (objekty) v definici třídy, a pak je zapojení do jiných tříd, které bude poskytovat další funkce, jako delegátů na váš základní třídy. Ale toto zapojení musí být maitained v kódu a bude nemotorné a náchylné k chybám. Objective C prostě předpokládá, že programátoři nejsou nejlepší na udržení tohoto decipline a zajišťuje omezení kompilátoru prosadit čistou implementaci.

Odpovězeno 19/06/2013 v 11:34
zdroj uživatelem

hlasů
9

Swift verze

Delegát je prostě třída, která dělá nějakou práci pro jiné třídy. Přečtěte si následující kód pro poněkud hloupé (ale doufejme, poučné) Hřiště příklad, který ukazuje, jak se to dělá v 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!"
}

V praxi delegáti jsou často používány v následujících situacích:

  1. Když třída potřebuje komunikovat nějaké informace do jiné třídy
  2. Když třída chce umožnit další třída jej přizpůsobit

Třídy nepotřebují vědět nic o předem vzájemně výjimkou, že třída delegát v souladu s požadovaným protokolem.

Velmi doporučuji přečtení následující dva články. Pomohli mi pochopit delegátů ještě lepší než ta dokumentace udělal.

Odpovězeno 05/11/2015 v 17:11
zdroj uživatelem

hlasů
8

řekněme máte třídu, kterou vyvinula a chtějí deklarovat vlastnost delegáta, aby bylo možné jej upozorní na některé události se stane:

@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

takže si deklarovat protokol v MyClasssouboru záhlaví (nebo samostatný hlavičkový soubor), a prohlásit požadované / volitelné ovladače událostí, které váš delegát musí / by měly zavést, pak vyhlásit nemovitost v MyClasstypu ( id< MyClassDelegate>), což znamená žádnou objektivní střední třídy C, který odpovídá protokol MyClassDelegate, zjistíte, že je vlastnost delegát je deklarován jako slabý, je to velmi důležité, aby se zabránilo udržet cyklus (nejčastěji delegát zachová MyClassinstance, takže pokud jste prohlásil delegát jako zadržet, a to jak z nich udrží navzájem a ani z nich bude vždy být propuštěn).

všimnete si také, že metody protokolu předá MyClassinstanci delegáta jako parametr, to je osvědčený postup v případě, že delegát chcete volat některé metody na MyClassinstanci a také pomáhá při delegát deklaruje sebe jako MyClassDelegatena více MyClassinstancí, jako když máte více UITableView'sinstance ve vaší ViewControllera prohlašuje, že jako UITableViewDelegatepro všechny z nich.

a uvnitř vašeho MyClassvám oznámit delegáta s deklarovanými události takto:

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

nejprve zkontrolujte, zda váš delegát reaguje na způsobu protokol, který se chystáte volat v případě, že delegát není jeho provedení a aplikace zhavaruje pak (i ​​když není vyžadována metoda protocol).

Odpovězeno 08/04/2015 v 13:24
zdroj uživatelem

hlasů
8

Ok, to není opravdu odpověď na tuto otázku, ale pokud hledáte vzhůru, jak vytvořit svůj vlastní delegáta možná něco mnohem jednodušší by mohlo být lepší pro vás odpověď.

I těžko realizovat své delegáty, protože jsem zřídka potřebují. Mohu mít jen jeden delegát na objekt delegáta. Takže pokud chcete, aby váš delegát na jednosměrné komunikaci / předávání dat, než jsou mnohem lepší s oznámeními.

NSNotification může předat objektů více než jednoho příjemce, a to je velmi snadné použití. Funguje to takto:

MyClass.m soubor by měl vypadat takto

#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

Chcete-li používat upozornění v jiných třídách: Přidat třídu jako pozorovatel:

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

Provádět voliče:

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

Nezapomeňte odstranit třídu jako pozorovatel, pokud

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
Odpovězeno 17/07/2013 v 05:58
zdroj uživatelem

hlasů
6

Zde je jednoduchý způsob, jak vytvořit delegátů

Vytvořte protokol h souboru. Ujistěte se, že je definována před použitím protokolu @class následované názvem UIViewController< As the protocol I am going to use is UIViewController class>.

Krok 1: Vytvoření nové třídy protokol s názvem „YourViewController“, která bude podtřídy třídy UIViewController a přiřadit tuto třídu do druhého ViewController.

Krok 2: Jděte do souboru „YourViewController“ a upravit jak je uvedeno níže:

#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

Metody definované v chování protokolu může být řízen s @optional a @required v rámci definice protokolu.

Krok: 3: Realizace delegáta

    #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

// testují, zda metoda byla definována dříve, než ji nazývat

 - (void) someMethodToCallDelegate {
     if ([[self delegate] respondsToSelector:@selector(defineDelegateMethodName:)]) {
           [self.delegate delegateMethodName:self]; 
     }
  }
Odpovězeno 29/09/2015 v 09:23
zdroj uživatelem

hlasů
5

Chcete-li vytvořit svůj vlastní delegáta, nejprve je třeba vytvořit protokol a prohlásit potřebné metody, aniž by se provádí. A pak implementovat tento protokol do své třídy záhlaví, kam chcete zavést delegáta nebo delegát metody.

Protokol musí být deklarován jako níže:

@protocol ServiceResponceDelegate <NSObject>

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

@end

Jedná se o prvotřídní služby, kde by měl být nějaký úkol provést. To ukazuje, jak definovat delegáta a jak nastavit delegáta. Ve třídě implementačního po úkol je splněn metody delegáta se nazývají.

@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

To je hlavní zobrazení třídy z místa, kde se třída službu s názvem nastavením delegáta k sobě. A také protokol je realizován ve třídě záhlaví.

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

- (void) go;

@end

@implementation viewController

//
//some methods
//

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

To je ono, a zaváděním metody delegáta v této třídě, bude kontrola vrátí po operaci / úkol je hotov.

Odpovězeno 03/08/2015 v 04:47
zdroj uživatelem

hlasů
1

Upozornění: jedná se o Swiftverzi, jak vytvořit delegate.

Takže, jaké jsou delegáti? ... ve vývoji softwaru, existují obecné řešení architektury pro opakované použití, které pomáhají řešit běžně se vyskytující problémy v daném kontextu, tyto „šablony“, abych tak řekl, jsou nejlépe známý jako návrhových vzorů. Delegáti jsou návrhový vzor, ​​který umožňuje jeden objekt posílat zprávy na jiný objekt, když určité události dojde. Představte si, že objekt A volá na objekt B provádět akce. Jakmile je akce dokončena, objekt A by vědět, že B splnil úkol a přijmout nezbytná opatření, to může být dosaženo pomocí delegátů!

Pro lepší vysvětlení, budu ukázat vám, jak vytvořit vlastní delegáta, který předává data mezi třídami, s Swift v jednoduché aplikaci, začít stahovat nebo klonováním tento startovací projekt a spusťte jej!

Můžete vidět aplikace se dvěma třídami, ViewController Aa ViewController B. B má dva pohledy, které na čepu změní barvu pozadí ViewController, nic příliš komplikované právo? dobře teď pojďme si, že jednoduchým způsobem také změnit barvu pozadí třídy A, když se názory na třídě B se závitem.

Problém je v tom, že tento výhled jsou součástí třídy B a nemají žádnou představu o tom, třída A, takže musíme najít způsob, jak komunikovat mezi těchto dvou tříd, a to je místo, kde delegace svítí. jsem rozdělil implementaci do 6 stupňů, takže můžete použít jako tahák, když ji budete potřebovat.

Krok 1: Podívejte se na krok Pragma značkou 1 v souboru ClassBVC a přidat

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

Prvním krokem je vytvoření protocol, v tomto případě budeme vytvářet protokol ve třídě B, uvnitř protokolu můžete vytvořit libovolný počet funkcí, které chcete na základě požadavků implementace. V tomto případě musíme jen jednu jednoduchou funkci, která přijímá volitelný UIColorjako argument. Je dobrým zvykem pojmenovat své protokoly přidání slova delegatena konci názvu třídy, v tomto případě ClassBVCDelegate.

Krok 2: Podívejte se na krok Pragma značkou 2, ClassVBCa přidat

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

Tady stačí vytvořit delegáta vlastnost pro třídu, tato vlastnost musí přijmout protocoltypu, a to by mělo být dobrovolné. Také byste měli přidat slabé slovo před majetku, aby se zabránilo zachovat cykly a potenciální úniky paměti, pokud nevíte, co to znamená neboj teď, jen je třeba přidat toto klíčové slovo.

Krok 3: Podívejte se na Pragma známky kroku 3 uvnitř handleTap methodv ClassBVCa přidat

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

Jedna věc, kterou byste měli vědět, spusťte aplikaci a klepněte na libovolném zobrazení, neuvidíte žádné nové chování a to je správná věc, kterou chci zdůraznit, je ale, že aplikace není to shazovat, když se delegát nazývá, a je to proto, že jsme ji vytvořit jako volitelnou hodnotu, a to je důvod, proč to nespadne ani přenesena dosud neexistuje. Pojďme teď jít do ClassAVCsouboru a dělat to, v přenesené pravomoci.

Krok 4: Podívejte se na krok Pragma známky 4 uvnitř metody handleTap v ClassAVCa přidat vedle svého druhu třídy, jako je tento.

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

Nyní ClassAVC přijala ClassBVCDelegateprotokol, můžete vidět, že váš kompilátor vám dává chybu, která říká: „Typ‚ClassAVC neodpovídá protokolu ‚ClassBVCDelegate‘, což znamená jen to, že jste ještě použít metody protokolu, si představit, že když třída a přijímá protokol je jako podepsání smlouvy s třídou B a tato smlouva říká, „Jakákoliv třída přijímání mi musí využít své funkce!“

Rychlá poznámka: Pokud jste přišel z Objective-Cpozadí jste pravděpodobně myslel, že můžete také držet hubu, že chyba by to metoda nepovinné, ale pro mé překvapení, a pravděpodobně i vy, Swiftjazyk nepodporuje volitelná protocols, pokud chcete, aby to můžete vytvořit rozšíření pro vaše protocolnebo použít @objc klíčové slovo ve své protocolrealizaci.

Osobně Mám-li vytvořit protokol s různými volitelnými metodami bych raději ji rozbít na jiný protocols, takhle budu následovat koncept dává jedinou odpovědnost vůči svým objektům, ale může se lišit v závislosti na konkrétní implementaci.

Zde je dobrý článek o doplňkových metod.

Krok 5: Podívejte se na Pragma známky kroku 5 uvnitř připravit metodou Segue a přidat

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

Zde jsme jen vytvořit instanci ClassBVCa přiřadit jeho delegáta pro sebe, ale to, co je samo tady? No, já je ClassAVC, která byla přenesena!

Krok 6: Konečně, podívejte se na pragma kroku 6 v ClassAVCa využijme funkcemi protocol, začít psát func changeBackgroundColor a uvidíte, že je to auto-dokončil ji pro vás. Můžete přidat libovolný implementaci uvnitř to, v tomto případě budeme jen změnit barvu pozadí, přidejte.

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

Nyní spusťte aplikaci!

Delegatesjsou všude, a pravděpodobně používat, aniž by si všimnout, pokud si vytvořit tableviewv minulosti jste použili delegace, kterou mnoho tříd UIKITprací kolem nich a mnoho dalších frameworkstaké řeší tyto hlavní problémy.

  • Vyhnout těsné spojení objektů.
  • Upravit chování a vzhled bez nutnosti podtřídy objekty.
  • Umožňují úkoly, které mají být zpracovány off do libovolného objektu.

Gratulujeme, právě jste implementovat vlastní delegáta, vím, že jste pravděpodobně na mysli, tolik starostí jen na to? No, delegace je velmi důležitý návrhový vzor pochopit, pokud chcete, aby se stal iOSdeveloper, a vždy mějte na paměti, že mají jeden až jeden vztah mezi objekty.

Můžete vidět původní návod zde

Odpovězeno 26/04/2017 v 05:27
zdroj uživatelem

hlasů
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;

Metoda:

-(void)delegateMEthod: (ArgType) arg{
}
Odpovězeno 19/12/2016 v 04:14
zdroj uživatelem

hlasů
0

Odpověď je vlastně odpověděl, ale rád bych, aby vám „tahák“ pro vytvoření delegáta:

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
Odpovězeno 16/03/2018 v 04:40
zdroj uživatelem

hlasů
0

Začněme příkladem, pokud bychom koupit výrobek online, prochází procesem, jako je doprava / dodávky zachází rozdílným teams.So pokud dostane zásilku dokončení lodní tým by měl oznámit dodání tým, a to by mělo být jeden na jednoho komunikaci jako vysílání tuto informaci by režijní pro ostatní lidi / prodejce chtít předat tyto informace pouze k potřebným lidem.

Takže pokud si myslíme, že co se týče naší aplikace, událost může být on-line objednávky a různé týmy mohou být stejně jako několika pohledů.

Zde je kód zvážit ShippingView as Doprava tým a DeliveryView jako dodání týmu:

//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
        //
    }
}
Odpovězeno 14/07/2017 v 10:14
zdroj uživatelem

hlasů
0

Podle mého pohledu vytvořit samostatnou třídu pro příslušnou metodu delegáta a můžete použít, kam chcete.

v mé vlastní 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;

Po tomto in.m souboru vytvořit pole s objekty,

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

Zde jsou všechny nastaveny na vlastní delegáta class.after, které můžete použít tuto metodu delegáta, kam want.for příklad ...

v mém dalším viewcontroller dovozu po tom

vytvořit akci pro volání metody delegáta takhle

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

Po této metodě volání delegáta takhle

- (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;
}
}
Odpovězeno 08/02/2017 v 09:30
zdroj uživatelem

hlasů
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. Implementovat metodu ve třídě .m - (neplatné) didRemoveCellWithTag: (NSInteger) značka {NSLog @ ( "tag% d", značka);

}

Odpovězeno 02/01/2017 v 16:31
zdroj uživatelem

hlasů
0

Delegovat: - Vytvoření

@protocol addToCartDelegate <NSObject>

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

@end

Poslat a prosím přiřadit delegáta pro zobrazení jste odesílání dat

[self.delegate addToCartAction:itemsModel isAdded:YES];
Odpovězeno 08/12/2016 v 10:50
zdroj uživatelem

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