Vím, jak delegáti pracují, a vím, jak jsem je používat.
Ale jak mohu vytvořit jim?
Vím, jak delegáti pracují, a vím, jak jsem je používat.
Ale jak mohu vytvořit jim?
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.)
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.
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ř.
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.
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.
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!");
}
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.
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ě.
Prosím! zkontrolujte jednoduchý krok za krokem tutoriál, aby pochopili, jak funguje Delegáti v iOS.
Vytvořil jsem dvě ViewControllers (pro odesílání dat z jednoho do druhého)
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.
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.
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:
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.
ř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).
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];
}
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];
}
}
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.
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.
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
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ěď 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
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
//
}
}
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;
}
}
//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);
}
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];