Ik weet hoe afgevaardigden werken, en ik weet hoe ik ze kan gebruiken.
Maar hoe kan ik ze te maken?
Ik weet hoe afgevaardigden werken, en ik weet hoe ik ze kan gebruiken.
Maar hoe kan ik ze te maken?
Een Objective-C gedelegeerde object die het toegewezen delegateeigenschap ander object. Om er een te maken, je gewoon definieert een klasse die de gemachtigde methoden die u geïnteresseerd bent implementeert, en markeer die klasse als de uitvoering van de afgevaardigde protocol.
Stel bijvoorbeeld dat u een UIWebView. Als u wilt zijn gedelegeerde implementeren webViewDidStartLoad:methode, zou je een klasse als dit te maken:
@interface MyClass<UIWebViewDelegate>
// ...
@end
@implementation MyClass
- (void)webViewDidStartLoad:(UIWebView *)webView {
// ...
}
@end
Dan kun je een instantie van MyClass maken en toe te wijzen als afgevaardigde van de web view's:
MyClass *instanceOfMyClass = [[MyClass alloc] init];
myWebView.delegate = instanceOfMyClass;
Aan de UIWebViewkant, het heeft waarschijnlijk code gelijkend op dit om te zien of de gemachtigde reageert op het webViewDidStartLoad:bericht met behulp van respondsToSelector:en stuur het indien van toepassing.
if([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
[self.delegate webViewDidStartLoad:self];
}
De gedelegeerde eigenschap zelf wordt kenmerkend aangegeven weak(ARC) of assign(pre-ARC) te vermijden lussen behouden, aangezien de gemachtigde van een object bevat vaak een sterke verwijzing naar dat object. (Bijvoorbeeld, teneinde controller vaak de gemachtigde van het oog bevat.)
Om uw eigen gedelegeerden te definiëren, moet je hun methodes ergens te verklaren, zoals besproken in de Apple Documenten op protocollen . Verklaart u meestal een formele protocol. De verklaring, geparafraseerd van UIWebView.h, zou er als volgt uitzien:
@protocol UIWebViewDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end
Dit is analoog aan een interface of abstracte basisklasse, want het creëert een speciaal type voor uw afgevaardigde, UIWebViewDelegatein dit geval. Delegate implementors zou hebben om dit protocol goed te keuren:
@interface MyClass <UIWebViewDelegate>
// ...
@end
En dan uitvoering van de werkwijzen die in het protocol. Voor methoden in het protocol wordt verklaard @optional(zoals de meeste afgevaardigde methoden), moet u controleren met -respondsToSelector:voordat u een bepaalde methode op.
Delegate methodes zijn meestal vernoemd te beginnen met de naam delegerende klasse, en neem de delegerende object als de eerste parameter. Ze hebben ook vaak een will-, should- of deden- vorm. Dus, webViewDidStartLoad:(eerste parameter is de web view) in plaats van loadStarted(waarbij geen parameters) bijvoorbeeld.
In plaats van na te gaan of een afgevaardigde reageert op een selector elke keer als we willen bericht, kunt u die informatie cachen wanneer gedelegeerden zijn ingesteld. Een zeer schone manier om dit te doen is om een bitveld te gebruiken, als volgt:
@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
Dan, in het lichaam, kunnen we controleren dat onze afgevaardigde behandelt berichten door de toegang tot onze delegateRespondsTostructuur, in plaats van door het sturen -respondsToSelector:over en weer.
Voordat protocollen bestond, was het gebruikelijk om gebruik maken van een categorie op NSObjectde methoden een afgevaardigde kon implementeren verklaren. Bijvoorbeeld, CALayertoch doet dit:
@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end
Dit vertelt in wezen de compiler dat elk object zou kunnen implementeren displayLayer:.
U zou dan gebruik maken van dezelfde -respondsToSelector:aanpak zoals hierboven beschreven om deze methode aan te roepen. De afgevaardigden gewoon de uitvoering van deze methode en de toe te wijzen delegatepand, en dat is het (er is geen verklaren je conformeren aan een protocol). Deze methode is gebruikelijk in Apple's bibliotheken, maar nieuwe code moet hiervoor gebruik maken van de meer moderne protocol aanpak, aangezien deze aanpak vervuilt NSObject(die autocomplete minder bruikbaar maakt) en maakt het moeilijk voor de compiler om u te waarschuwen over typefouten en soortgelijke fouten.
De goedgekeurde antwoord is geweldig, maar als u op zoek bent naar een 1 minuut antwoord proberen:
MyClass.h bestand moet er als volgt uitzien (voeg afgevaardigde regels met commentaar!)
#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 bestand moet er als volgt uitzien
#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
Om uw afgevaardigde te gebruiken in een andere klasse (UIViewController genoemd MyVC in dit geval) 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
Uitvoering delegeren werkwijze
- (void) myClassDelegateMethod: (MyClass *) sender {
NSLog(@"Delegates are great!");
}
Bij gebruik van de formele protocol methode voor het maken afgevaardigde steun, heb ik geconstateerd dat je kunt zorgen voor een goede controle van het type (alhoewel, runtime, geen tijd te compileren) door het toevoegen van iets als:
if (![delegate conformsToProtocol:@protocol(MyDelegate)]) {
[NSException raise:@"MyDelegate Exception"
format:@"Parameter does not conform to MyDelegate protocol at line %d", (int)__LINE__];
}
in de gemachtigde accessor (setDelegate) code. Dit helpt fouten te minimaliseren.
Misschien is dit meer langs de lijnen van wat je mist:
Als u vanuit een C ++ als oogpunt afgevaardigden duurt een beetje wennen - maar in principe 'ze gewoon werken'.
De manier waarop het werkt is dat je een object dat je hebt geschreven als afgevaardigde voor NSWindow te stellen, maar uw object heeft slechts implementaties (methoden) voor een of een paar van de vele mogelijke afgevaardigde methoden. Dus iets gebeurt, en NSWindowwil uw object noemen - het maakt gebruik van slechts Objective-c's respondsToSelectormethode om te bepalen of uw object wil dat methode genaamd, en vervolgens het noemt. Dit is hoe Objective-C werkt - methoden worden opgezocht op de vraag.
Het is volstrekt triviaal om dit te doen met uw eigen objecten, is er niets bijzonders aan de hand, zou je bijvoorbeeld een NSArrayvan 27 objecten, alle verschillende soorten objecten, slechts 18 een aantal van hen hebben de methode -(void)setToBue;De andere 9 niet. Dus om te bellen setToBlueop elk van 18, die het nodig hebben gedaan, zoiets als dit:
for (id anObject in myArray)
{
if ([anObject respondsToSelector:@selector(@"setToBlue")])
[anObject setToBlue];
}
Het andere ding over gedelegeerden is dat ze niet worden vastgehouden, zodat u altijd aan de gemachtigde ingesteld nilin uw MyClass deallocmethode.
Please! check onderstaande eenvoudige stap voor stap uitleg om te begrijpen hoe Afgevaardigden werkt in iOS.
Ik heb twee viewcontrollers gemaakt (voor het verzenden van gegevens van de ene naar de andere)
Als een goede praktijk aanbevolen door Apple, het is goed voor de gedelegeerde (dat is een protocol per definitie), om te voldoen aan NSObjectprotocol.
@protocol MyDelegate <NSObject>
...
@end
En om mogelijke methoden binnen uw delegate (dwz methoden die niet noodzakelijkerwijs worden toegepast) te maken, kunt u gebruik maken van @optionalannotatie als volgt uit:
@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
Dus bij het gebruik van methoden die je hebt opgegeven als optioneel, moet je (in je klas) te controleren met respondsToSelectorof het uitzicht (die voldoen aan uw afgevaardigde) daadwerkelijk heeft geïmplementeerd uw optionele methode (s) of niet.
Ik denk dat al deze antwoorden te maken veel zin als je eenmaal afgevaardigden begrijpen. Persoonlijk Ik kwam uit het land van C / C ++ en daarvoor procedurele talen zoals Fortran etc dus hier is mijn 2 minuten om op het vinden van soortgelijke analogen in C ++ paradigma.
Als ik afgevaardigden uit te leggen aan een C ++ / Java programmeur zou ik zeggen
Wat zijn de afgevaardigden? Dit zijn statische verwijzingen naar klassen binnen een andere klasse. Zodra u een pointer toe te wijzen, kunt u bellen functies / methoden in die klasse. Vandaar dat enkele functies van de klas zijn "gedelegeerd" (In C ++ wereld - pointer naar een klasse object pointer) naar een andere klasse.
Wat zijn de protocollen? Conceptueel dient het als vergelijkbaar doel als de header-bestand van de klasse die u toewijst als afgevaardigde klasse. Een protocol is een expliciete manier om te bepalen wat methoden moet in de klas die is wijzer werd ingesteld als een afgevaardigde binnen een klasse uit te voeren.
Hoe kan ik iets dergelijks in C ++ doen? Als u hebt geprobeerd om dit te doen in C ++, zou je door het definiëren van verwijzingen naar klassen (objecten) in de definitie van de klasse en vervolgens bedrading ze aan andere klassen die extra functies zal bieden als deelnemers aan uw basisklasse. Maar dit bedrading moet worden maitained binnen de code en zal onhandig zijn en foutgevoelig. Objective C veronderstelt gewoon dat programmeurs zijn niet van de beste op het handhaven van deze decipline en biedt compiler beperkingen om een schone implementatie af te dwingen.
Een afgevaardigde is gewoon een klasse die wat werk doet voor een andere klasse. Lees de volgende code voor een ietwat domme (maar hopelijk verhelderend) Speeltuin voorbeeld dat laat zien hoe dit gebeurt 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 de praktijk worden de afgevaardigden vaak gebruikt in de volgende situaties
De lessen hoeven niet om iets over elkaar te voren, behalve dat de gedelegeerde klasse voldoet aan de vereiste protocol te leren kennen.
Ik beveel het lezen van de volgende twee artikelen. Ze hielp me afgevaardigden zelfs beter dan het te begrijpen documentatie deed.
laten we zeggen je hebt een klasse die je ontwikkeld en wilt verklaren een afgevaardigde woning aan kunnen om het te waarschuwen wanneer een bepaalde gebeurtenis gebeurt:
@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
dus je verklaren een protocol in MyClassheader-bestand (of een aparte header-bestand), en verklaren de vereiste / optionele event handlers dat de gemachtigde moet / moeten uitvoeren, dan is een eigenschap verklaren MyClassvan het type ( id< MyClassDelegate>), wat betekent dat geen objectieve c klasse die voldoet aan het protocol MyClassDelegate, zult u merken dat het pand afgevaardigde wordt verklaard als een zwakke, dit is erg belangrijk om te voorkomen dat cyclus behouden (meestal de gemachtigde behoudt de MyClassinstantie dus als je de gemachtigde als behouden, beiden zullen elkaar en geen van beide te behouden verklaard van hen ooit zal worden uitgebracht).
vindt u ook dat het protocol methoden passeert de merken MyClassbijvoorbeeld om de gemachtigde als parameter, dan is dit de beste praktijken in het geval dat de gedelegeerde wilt een aantal methoden op te bellen MyClassaanleg en helpt ook bij de gemachtigde zelf verklaart als MyClassDelegatemeerdere MyClassinstanties, zoals wanneer je meerdere hebt UITableView'sinstances in uw ViewControlleren verklaart zich als een UITableViewDelegateom ze allemaal te.
en in je MyClassu op de hoogte van de gemachtigde met verklaarde gebeurtenissen als volgt:
if([_delegate respondsToSelector:@selector(myClass: requiredEventHandlerWithParameter:)])
{
[_delegate myClass:self requiredEventHandlerWithParameter:(ParamType*)param];
}
u eerst controleren of uw afgevaardigde reageert op het protocol methode die u op het punt om te bellen in het geval dat de gemachtigde niet implementeren en de app zal vervolgens crashen (zelfs als het protocol methode vereist is) zijn.
Ok, dit is niet echt een antwoord op de vraag, maar als u op zoek bent naar boven hoe je je eigen afgevaardigde maken misschien iets veel eenvoudiger zou een beter antwoord voor je.
Ik nauwelijks uit te voeren mijn afgevaardigden omdat ik zelden nodig. Ik kan slechts één afgevaardigde voor een gedelegeerde object te hebben. Dus als u wilt dat uw afgevaardigde van eenrichtingscommunicatie / doorgeven van gegevens dan je veel beter af met meldingen.
NSNotification kunnen voorwerpen door te geven aan meer dan één ontvangers en het is zeer makkelijk te gebruiken. Het werkt als volgt:
MyClass.m bestand moet er als volgt uitzien
#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
Als u uw melding in een andere klassen: klasse toevoegen als waarnemer:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(otherClassUpdatedItsData:) name:@"myClassUpdatedData" object:nil];
Implementeren van de selector:
- (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
}
Vergeet niet om uw klas te verwijderen als waarnemer als
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Hier is een eenvoudige methode om te creëren de deelnemers
Maak Protocol in .h bestand. Zorg ervoor dat wordt gedefinieerd voor het protocol met behulp van @class gevolgd door de naam van de UIViewController< As the protocol I am going to use is UIViewController class>.
Stap 1: Maak een nieuwe klasse protocol met de naam "YourViewController", die de subklasse van UIViewController klasse zal zijn en deze klasse toe te wijzen aan de tweede ViewController.
Stap 2: Ga naar de "YourViewController" bestand en zoals hieronder wijzigen:
#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
De in het protocol gedrag werkwijzen kunnen worden bediend met @optional en @required kader van de protocoldefinitie.
Stap 3: Implementatie van 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
// testen of de methode is gedefinieerd voordat je het noemen
- (void) someMethodToCallDelegate {
if ([[self delegate] respondsToSelector:@selector(defineDelegateMethodName:)]) {
[self.delegate delegateMethodName:self];
}
}
Om uw eigen afgevaardigde te maken, moet u eerst een protocol te maken en verklaren de nodige methoden, zonder de uitvoering. En dan is de uitvoering van dit protocol in uw header klasse waar u de gemachtigde of afgevaardigde methoden toe te passen.
Een protocol moet worden aangegeven als hieronder:
@protocol ServiceResponceDelegate <NSObject>
- (void) serviceDidFailWithRequestType:(NSString*)error;
- (void) serviceDidFinishedSucessfully:(NSString*)success;
@end
Dit is de dienst klasse, waar een taak moet worden gedaan. Het laat zien hoe om te delegeren en hoe aan de gemachtigde stellen definiëren. In de klasse tenuitvoerlegging na de taak is voltooid van de gemachtigde van de methoden worden genoemd.
@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
Dit is de belangrijkste weergave klasse van waaruit de dienst klasse wordt aangeroepen door het instellen van de afgevaardigde aan zichzelf. En ook het protocol is geïmplementeerd in de header klasse.
@interface viewController: UIViewController <ServiceResponceDelegate>
{
ServiceClass* _service;
}
- (void) go;
@end
@implementation viewController
//
//some methods
//
- (void) go
{
_service = [[ServiceClass alloc] init];
[_service setDelegate:self];
[_service someTask];
}
Dat is het, en door de uitvoering delegeren methoden in deze klasse, zal de controle terug te komen zodra de operatie / taak wordt uitgevoerd.
Disclaimer: dit is de Swiftversie van hoe je een te maken delegate.
Dus, wat zijn de afgevaardigden? ... in de ontwikkeling van software, er algemene herbruikbare oplossing architecturen die helpen om veel voorkomende problemen binnen een bepaalde context op te lossen, deze “templates”, om zo te zeggen, zijn het best bekend als design patterns. Gedelegeerden een ontwerppatroon waarmee een doel om berichten naar een ander object wordt verzonden wanneer een bepaalde gebeurtenis plaatsvindt. Stel je een object A vraagt een object B om een actie uit te voeren. Zodra de actie is voltooid, moet object A weten dat B de taak heeft afgerond en de nodige actie, kan dit worden bereikt met de hulp van de afgevaardigden!
Voor een betere verklaring, ga ik je laten zien hoe u een aangepaste afgevaardigde die gegevens tussen klassen gaat maken, met Swift in een eenvoudige applicatie, beginnen met het downloaden of het klonen van deze starter project en voer het uit!
U kunt een app te zien met twee klassen, ViewController Aen ViewController B. B heeft twee standpunten die op de tap verandert de achtergrondkleur van het ViewController, niets te ingewikkeld toch? goed laten we nu denken op een eenvoudige manier om ook de achtergrondkleur van klasse A veranderen als de opvattingen over klasse B worden getapt.
Het probleem is dat deze standpunten zijn onderdeel van de klasse B en hebben geen idee over de klasse A, dus we moeten een manier om te communiceren tussen deze twee klassen te vinden, en dat is waar de delegatie schijnt. Ik verdeelde de implementatie in 6 stappen, zodat u deze kunt gebruiken als spiekbriefje wanneer je het nodig hebt.
Stap 1: Zoek de pragma mark stap 1 in ClassBVC bestand en voeg deze
//MARK: step 1 Add Protocol here.
protocol ClassBVCDelegate: class {
func changeBackgroundColor(_ color: UIColor?)
}
De eerste stap is het creëren van een protocol, in dit geval, zullen we het protocol in klasse B te creëren, in het protocol dat u kunt zo veel functies die u wilt op basis van de eisen van uw implementatie te maken. In dit geval hebben we slechts een simpele functie die een optionele accepteert UIColorals argument. Is een goede gewoonte om uw protocollen toevoeging van het woord een naam delegateaan het einde van de naam van de klasse, in dit geval ClassBVCDelegate.
stap 2: Kijk voor de pragma mark stap 2 in ClassVBCen voeg dit
//MARK: step 2 Create a delegate property here.
weak var delegate: ClassBVCDelegate?
Hier hebben we gewoon een afgevaardigde eigenschap voor de klasse, moet deze woning is de te nemen protocolsoort, en het moet facultatief zijn. Ook moet u de zwakke zoekwoord toe te voegen voordat de eigenschap om te voorkomen dat vast te houden cycli en potentiële geheugenlekken, als je niet weet wat dat betekent geen zorgen voor nu, alleen niet vergeten om dit zoekwoord toe te voegen.
Stap 3: Kijk naar de pragma teken stap 3 in de handleTap methodin ClassBVCen voeg dit
//MARK: step 3 Add the delegate method call here.
delegate?.changeBackgroundColor(tapGesture.view?.backgroundColor)
Een ding dat je moet weten, de app draaien en tik op elke weergave, zult u geen nieuw gedrag te zien en dat is juist, maar het ding dat ik wil wijzen is dat de app het niet crashen wanneer de afgevaardigde wordt genoemd, en het is omdat we het te maken als een optionele waarde en dat is waarom het niet eens de gedelegeerde zal crashen bestaat nog niet. Laten we nu naar ClassAVChet bestand en het te maken, de gedelegeerde.
stap 4: Kijk naar de pragma teken stap 4 in de handleTap methode in ClassAVCen voeg deze naast uw klastype als deze.
//MARK: step 4 conform the protocol here.
class ClassAVC: UIViewController, ClassBVCDelegate {
}
Nu ClassAVC heeft het ClassBVCDelegateprotocol, kunt u zien dat uw compiler geeft u een foutmelding die zegt “Type 'ClassAVC voldoet niet aan het protocol 'ClassBVCDelegate' en dit betekent alleen dat je niet de methoden van het protocol nog niet gebruiken, stel dat wanneer klasse a het protocol aanneemt is als het ondertekenen van een contract met klasse B en dit contract zegt: “Elke klasse aanneming me MOET mijn functies te gebruiken!”
Quick note: Als je uit een Objective-Cachtergrond bent u waarschijnlijk denken dat je ook kunt opsluiten die fout maken van die methode optioneel, maar voor mijn verbazing, en waarschijnlijk ook van jou, Swiftde taal niet ondersteunt optioneel protocols, als je wilt om het te doen die u kunt maken een uitbreiding voor je protocolof gebruik de @objc zoekwoord in uw protocolimplementatie.
Persoonlijk, als ik moet een protocol met verschillende mogelijke methoden zou ik liever om het te breken in verschillende creëren protocols, op die manier zal ik het concept van het geven van een enkele verantwoordelijkheid om mijn objecten te volgen, maar het kan variëren op basis van de specifieke implementatie.
Hier is een goed artikel over mogelijke methoden.
Stap 5: Kijk naar de pragma mark stap 5 in de voorbereiding op segue methode en voeg deze toe
//MARK: step 5 create a reference of Class B and bind them through the `prepareforsegue` method.
if let nav = segue.destination as? UINavigationController, let classBVC = nav.topViewController as? ClassBVC {
classBVC.delegate = self
}
Hier zijn we gewoon het creëren van een instantie van ClassBVCen zijn afgevaardigde toe te wijzen aan zichzelf, maar wat is zelf hier? goed, zelf is het ClassAVCdie is gedelegeerd!
Stap 6: Tot slot, kijk voor de pragma stap 6 in ClassAVCen laten we gebruik maken van de functies van de protocol, begint te typen func changeBackgroundColor en je zult zien dat het automatisch invullen van het voor u. U kunt elke implementatie toe te voegen binnen het, in dit voorbeeld, zullen we gewoon de achtergrondkleur te veranderen, voeg dit toe.
//MARK: step 6 finally use the method of the contract
func changeBackgroundColor(_ color: UIColor?) {
view.backgroundColor = color
}
Nu voert u de app!
Delegateszijn overal en u waarschijnlijk gebruik ze zonder eens in de gaten, als je het creëren van een tableviewin het verleden je hebt gebruikt delegatie, vele klassen van UIKITwerken om hen heen en vele andere frameworksook, ze oplossen van deze belangrijkste problemen.
Gefeliciteerd, je gewoon implementeren van een aangepaste afgevaardigde, ik weet dat je waarschijnlijk denken, zo veel moeite alleen voor dit? goed, delegatie is een zeer belangrijke ontwerp patroon om te begrijpen als je wilt om een te worden iOSontwikkelaar, en altijd in gedachten houden dat ze een op een relatie tussen objecten.
U kunt de originele tutorial zie hier
ViewController.h
@protocol NameDelegate <NSObject>
-(void)delegateMEthod: (ArgType) arg;
@end
@property id <NameDelegate> delegate;
ViewController.m
[self.delegate delegateMEthod: argument];
MainViewController.m
ViewController viewController = [ViewController new];
viewController.delegate = self;
Methode:
-(void)delegateMEthod: (ArgType) arg{
}
Antwoord is eigenlijk beantwoord, maar ik wil u een "spiekbriefje" te geven voor het maken van een afgevaardigde:
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
Laten we beginnen met een voorbeeld, als we een product online koopt, gaat het door proces zoals de scheepvaart / levering behandeld door verschillende teams.So indien de scheepvaart wordt uitgevoerd, moet de scheepvaart team levering team te melden en moet 1-1 communicatie als het uitzenden van deze informatie zijn overhead zou zijn voor andere mensen / leverancier zou willen om deze informatie door te geven alleen voor benodigde mensen.
Dus als we denken in termen van onze app, kan een gebeurtenis van een online bestelling en verschillende teams kan worden als meerdere weergaven.
Hier is code overwegen ShippingView als Shipping team & DeliveryView als levering team:
//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
//
}
}
In mijn standpunt te creëren aparte klasse voor dat delegeren methode en u kunt gebruiken waar je wilt.
in mijn Custom 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;
na dat in.m bestand aan te maken array met objecten,
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
CGFloat rowHeight = 44.0f;
return rowHeight;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return isFiltered?[self.array1DropDown count]:[self.array2DropDown count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = @"TableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
if (self.delegate) {
if (self.dropDownType == DDCITY) {
cell.textLabel.text = [self.array1DropDown objectAtIndex:indexPath.row];
}
else if (self.dropDownType == DDSTATE) {
cell.textLabel.text = [self.array2DropDown objectAtIndex:indexPath.row];
}
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self dismissViewControllerAnimated:YES completion:^{
if(self.delegate){
if(self.dropDownType == DDCITY){
[self.delegate dropDownDidSelectItemWithString:[self.array1DropDown objectAtIndex:indexPath.row] DropDownType:self.dropDownType];
}
else if (self.dropDownType == DDSTATE) {
[self.delegate dropDownDidSelectItemWithString:[self.array2DropDown objectAtIndex:indexPath.row] DropDownType:self.dropDownType];
}
}
}];
}
Hier worden alle zijn ingesteld voor Custom afgevaardigde class.after dat u deze delegeren methode waar u want.for bijvoorbeeld kunt gebruiken ...
in mijn andere ViewController import na dat
creëren actie voor het bellen delegeren methode zoals deze
- (IBAction)dropDownBtn1Action:(id)sender {
DropDownViewController *vehicleModelDropView = [[DropDownViewController alloc]init];
vehicleModelDropView.dropDownType = DDCITY;
vehicleModelDropView.delegate = self;
[self presentViewController:vehicleModelDropView animated:YES completion:nil];
}
na dat gesprek delegeren methode zoals deze
- (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. Implementeren van de methode in de klasse .m - (void) didRemoveCellWithTag: (NSInteger) tag {NSLog @ ( "Tag% d", markering);
}
Delegeer: - Creëer
@protocol addToCartDelegate <NSObject>
-(void)addToCartAction:(ItemsModel *)itemsModel isAdded:(BOOL)added;
@end
Stuur en kunt u toewijzen delegeren om te bekijken u verzendt data
[self.delegate addToCartAction:itemsModel isAdded:YES];