Je sais comment les délégués travaillent, et je sais comment je peux les utiliser.
Mais comment puis-je les créer?
Je sais comment les délégués travaillent, et je sais comment je peux les utiliser.
Mais comment puis-je les créer?
Un délégué Objective-C est un objet qui a été attribué à la delegatepropriété un autre objet. Pour créer un, vous définissez simplement une classe qui implémente les méthodes de délégués qui vous intéressent, et marquer cette classe comme la mise en œuvre du protocole de délégué.
Par exemple, supposons que vous avez un UIWebView. Si vous souhaitez mettre en œuvre son délégué de webViewDidStartLoad:la méthode, vous pouvez créer une classe comme ceci:
@interface MyClass<UIWebViewDelegate>
// ...
@end
@implementation MyClass
- (void)webViewDidStartLoad:(UIWebView *)webView {
// ...
}
@end
Ensuite, vous pouvez créer une instance de MyClass et lui attribuer en tant que délégué de la vue Web:
MyClass *instanceOfMyClass = [[MyClass alloc] init];
myWebView.delegate = instanceOfMyClass;
Sur le UIWebViewcôté, il a probablement un code similaire à ceci pour voir si le délégué répond au webViewDidStartLoad:message en utilisant respondsToSelector:et l' envoyer le cas échéant.
if([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
[self.delegate webViewDidStartLoad:self];
}
La propriété est généralement délégué lui - même déclaré weak(en ARC) ou assign(pré-ARC) afin d' éviter de conserver des boucles, puisque le délégué d'un objet contient souvent une forte référence à cet objet. (Par exemple, un contrôleur de vue est souvent le délégué d'une vue qu'il contient.)
Pour définir vos propres délégués, vous devrez déclarer leurs méthodes quelque part, comme indiqué dans la pomme Docs sur les protocoles . Vous déclarez habituellement un protocole formel. La déclaration, paraphrase de UIWebView.h, ressemblerait à ceci:
@protocol UIWebViewDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end
Ceci est analogue à une interface ou une classe de base abstraite, car elle crée un type spécial pour votre délégué, UIWebViewDelegatedans ce cas. Délégué implémenteurs devraient adopter ce protocole:
@interface MyClass <UIWebViewDelegate>
// ...
@end
Et mettre en œuvre ensuite les méthodes dans le protocole. Pour les méthodes déclarées dans le protocole comme @optional(comme la plupart des méthodes de délégués), vous devez vérifier avec -respondsToSelector:avant d' appeler une méthode particulière à ce sujet .
Méthodes Déléguer sont généralement nommés en commençant par le nom de la classe délégante, et prennent l'objet délégante comme premier paramètre. Ils utilisent aussi souvent une forme will-, doit si possible , ou DID. Donc, webViewDidStartLoad:(premier paramètre est l'affichage Web) plutôt que loadStarted(en aucun paramètre) par exemple.
Au lieu de vérifier si un délégué répond à un sélecteur chaque fois que nous voulons un message, vous pouvez mettre en cache ces informations lorsque les délégués sont fixés. Une façon très propre de le faire est d'utiliser un champ de bits, comme suit:
@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
Puis, dans le corps, nous pouvons vérifier que notre délégué gère les messages en accédant à notre delegateRespondsTostruct, plutôt que par l' envoi d' -respondsToSelector:encore et encore.
Avant protocoles existaient, il était courant d'utiliser une catégorie sur NSObjectde déclarer les méthodes un délégué pourrait mettre en œuvre. Par exemple, le CALayerfait encore:
@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end
Cela indique essentiellement le compilateur que tout objet peut mettre en œuvre displayLayer:.
Vous pouvez ensuite utiliser la même -respondsToSelector:approche que décrit ci - dessus pour appeler cette méthode. Les délégués mettent en œuvre simplement cette méthode et attribuer la delegatepropriété, et c'est tout (il n'y a pas de déclarer vous conformer à un protocole). Cette méthode est courante dans les bibliothèques d'Apple, mais le nouveau code devrait utiliser l'approche du protocole plus moderne ci - dessus, étant donné que cette pollue approche NSObject( ce qui rend autocomplete moins utile) et rend difficile pour le compilateur de vous mettre en garde contre les fautes de frappe et des erreurs similaires.
La réponse approuvée est grande, mais si vous cherchez une réponse 1 minute, essayez ceci:
MyClass.h fichier devrait ressembler à ceci (ajouter des lignes de délégués des commentaires!)
#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
fichier MyClass.m devrait ressembler à ceci
#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
Pour utiliser votre délégué dans une autre classe (UIViewController appelé MyVC dans ce cas) 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
Mettre en oeuvre la méthode de délégué
- (void) myClassDelegateMethod: (MyClass *) sender {
NSLog(@"Delegates are great!");
}
Lorsque vous utilisez la méthode de protocole formel pour créer le soutien des délégués, j'ai trouvé que vous pouvez vous assurer bon type de contrôle (bien que, l'exécution, la compilation pas le temps) en ajoutant quelque chose comme:
if (![delegate conformsToProtocol:@protocol(MyDelegate)]) {
[NSException raise:@"MyDelegate Exception"
format:@"Parameter does not conform to MyDelegate protocol at line %d", (int)__LINE__];
}
dans votre code accesseur délégué (setDelegate). Cela permet de minimiser les erreurs.
Peut-être cela est plus le long des lignes de ce qui vous manque:
Si vous venez d'un point de vue de C ++ comme, les délégués prennent un peu de temps pour s'y habituer - mais, fondamentalement, « ils fonctionnent ».
La façon dont cela fonctionne est que vous définissez un objet que vous avez écrit en tant que délégué à NSWindow, mais votre objet n'a que des implémentations (méthodes) pour une ou quelques - unes des nombreuses méthodes de délégués possibles. Donc , quelque chose se passe, et NSWindowveut appeler votre objet - il utilise simplement de Objective-c respondsToSelectorméthode pour déterminer si votre objet veut que méthode appelée, puis l' appelle. Voilà comment fonctionne-c objectif - les méthodes sont cherchés sur demande.
Il est tout à fait banal de le faire avec vos propres objets, il n'y a rien de spécial, vous pouvez par exemple avoir un NSArray27 objets, tous les différents types d'objets, seulement 18 certains d'entre eux ayant la méthode -(void)setToBue;L'autre 9 ne sont pas. Donc , pour appeler setToBluesur tous les 18 qui en ont besoin fait, quelque chose comme ceci:
for (id anObject in myArray)
{
if ([anObject respondsToSelector:@selector(@"setToBlue")])
[anObject setToBlue];
}
L'autre chose au sujet des délégués est qu'ils ne sont pas conservés, donc vous devez toujours définir le délégué nildans votre MyClass deallocméthode.
S'il vous plaît! vérifier ci-dessous simple étape par étape tutoriel pour comprendre comment les délégués fonctionne dans iOS.
J'ai créé deux ViewControllers (pour envoyer des données d'un à l'autre)
En tant que bonne pratique recommandée par Apple, il est bon pour le délégué (qui est un protocole, par définition), pour se conformer au NSObjectprotocole.
@protocol MyDelegate <NSObject>
...
@end
Et de créer des méthodes en option au sein de votre délégué (c. -à -méthodes qui ne doivent pas être mises en œuvre nécessairement), vous pouvez utiliser l' @optionalannotation comme ceci:
@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
Donc , lorsque vous utilisez les méthodes que vous avez spécifié en option, vous devez (dans votre classe) vérifier avec respondsToSelectorsi la vue (qui est conforme à votre délégué) a effectivement mis en œuvre votre méthode facultative (s) ou non.
Je pense que toutes ces réponses font beaucoup de sens une fois que vous comprenez les délégués. Personnellement, je suis venu de la terre de C / C ++ et avant que les langues de procédure comme Fortran etc voici donc mes 2 min prennent trouver des analogues similaires paradigme C ++.
Si je devais expliquer les délégués à un C ++ / programmeur Java Je dirais
Quels sont les délégués? Ce sont des pointeurs statiques à des classes dans une autre classe. Une fois que vous attribuez un pointeur, vous pouvez appeler des fonctions / méthodes dans cette classe. D'où certaines fonctions de votre classe sont « délégués » (Dans le monde de C - pointeur par un pointeur d'objet de classe) à une autre classe.
Quels sont les protocoles? Conceptuellement, il sert le même but que le fichier d'en-tête de la classe que vous assignez en tant que classe de délégué. Un protocole est une façon explicite de définir les méthodes doivent être mises en œuvre dans la classe qui est le pointeur a été défini comme un délégué au sein d'une classe.
Comment puis-je faire quelque chose de similaire en C ++? Si vous avez essayé de le faire en C ++, vous en définissant des pointeurs vers les classes (objets) dans la définition de la classe, puis les câbler à d'autres classes qui fourniront des fonctions supplémentaires en tant que délégués à votre classe de base. Mais ce câblage doit être maitained dans le code et sera maladroit et sujette à l'erreur. Objectif C suppose simplement que les programmeurs ne sont pas mieux à maintenir ce decipline et fournit des restrictions du compilateur pour appliquer une mise en œuvre propre.
Un délégué est juste une classe qui fait un travail pour une autre classe. Lire le code suivant pour un peu ridicule (mais nous espérons éclairer) exemple aire de jeu qui montre comment cela se fait dans 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!"
}
Dans la pratique, les délégués sont souvent utilisés dans les situations suivantes
Les classes ne ont pas besoin de savoir quoi que ce soit au sujet de l'autre à l'avance, sauf que la classe déléguée est conforme au protocole requis.
Je recommande vivement de lire les deux articles suivants. Ils m'a aidé à comprendre les délégués encore mieux que la documentation a fait.
permet de dire que vous avez une classe que vous avez développé et que vous voulez déclarer une propriété de délégué pour être en mesure de notifier quand un événement se produit:
@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
de sorte que vous déclarez un protocole dans le MyClassfichier d' en- tête (ou un fichier d' en- tête séparé), et je raconterai les gestionnaires d'événements requis / option que votre délégué doit / devrait mettre en œuvre, puis déclarer une propriété MyClassde type ( id< MyClassDelegate>) ce qui signifie que toute classe objective c conforme aux le protocole MyClassDelegate, vous remarquerez que la propriété déléguée est déclarée comme faible, ce qui est très important pour éviter de conserver le cycle ( le plus souvent le délégué conserve l' MyClassexemple si vous avez déclaré le délégué comme retiendrez, deux d'entre eux conserveront l'autre et ni d'entre eux ne sera jamais publié).
vous remarquerez également que les méthodes de protocole passe l' MyClassinstance au délégué en tant que paramètre, c'est la meilleure pratique au cas où le délégué veulent appeler des méthodes sur MyClassexemple et contribue également lorsque le délégué se déclare comme MyClassDelegateà plusieurs MyClassinstances, comme lorsque vous avez plusieurs UITableView'scas dans votre ViewControlleret se déclare comme UITableViewDelegateà tous.
et à l' intérieur de votre MyClassvous informiez le délégué des événements déclarés comme suit:
if([_delegate respondsToSelector:@selector(myClass: requiredEventHandlerWithParameter:)])
{
[_delegate myClass:self requiredEventHandlerWithParameter:(ParamType*)param];
}
vous devez d'abord vérifier si votre délégué répond à la méthode de protocole que vous êtes sur le point d'appeler au cas où le délégué ne met pas en œuvre et l'application se bloque alors (même si la méthode de protocole est nécessaire).
Ok, ce n'est pas vraiment une réponse à la question, mais si vous êtes à la recherche jusqu'à la façon de faire votre propre délégué peut-être quelque chose de beaucoup plus simple pourrait être une meilleure réponse pour vous.
Je mets en œuvre à peine mes délégués parce que j'ai rarement besoin. Je ne peux avoir qu'un seul délégué pour un délégué. Donc, si vous voulez que votre délégué pour une communication de données / passage moyen que vous êtes beaucoup mieux avec les notifications.
NSNotification peut passer des objets à plus d'un des destinataires et il est très facile à utiliser. Il fonctionne comme ceci:
fichier MyClass.m devrait ressembler à ceci
#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
Pour utiliser votre notification dans un autre cours: Ajouter une classe à titre d'observateur:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(otherClassUpdatedItsData:) name:@"myClassUpdatedData" object:nil];
Mettre en place le sélecteur:
- (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
}
Ne pas oublier d'enlever votre classe comme un observateur si
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Voici une méthode simple pour créer des délégués
Créer protocole dans le fichier .h. Assurez-vous que est défini avant le protocole en utilisant @class suivi du nom de la UIViewController< As the protocol I am going to use is UIViewController class>.
Etape 1: Créer un nouveau protocole de classe nommée « YourViewController » qui sera la sous - classe de la classe UIViewController et attribuer cette classe à la deuxième ViewController.
Étape 2: Accédez au fichier « YourViewController » et le modifier comme ci - dessous:
#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
Les méthodes définies dans le comportement du protocole peuvent être contrôlés avec @optional et @Required dans le cadre de la définition de protocole.
Étape 3: Mise en œuvre du délégué
#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
// test si la méthode a été définie avant de l'appeler
- (void) someMethodToCallDelegate {
if ([[self delegate] respondsToSelector:@selector(defineDelegateMethodName:)]) {
[self.delegate delegateMethodName:self];
}
}
Pour créer votre propre délégué, vous devez d'abord créer un protocole et déclarer les méthodes nécessaires, sans mettre en œuvre. Et puis mettre en œuvre ce protocole dans votre classe d'en-tête où vous souhaitez mettre en œuvre le délégué ou délégué méthodes.
Un protocole doit être déclaré comme ci-dessous:
@protocol ServiceResponceDelegate <NSObject>
- (void) serviceDidFailWithRequestType:(NSString*)error;
- (void) serviceDidFinishedSucessfully:(NSString*)success;
@end
Ceci est la classe de service où doit se faire une tâche. Il montre comment définir délégué et la façon de définir le délégué. Dans la classe de mise en œuvre une fois la tâche terminée les méthodes sont appelées du délégué.
@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
C'est la principale classe de vue où la classe de service est appelé en réglant le délégué à lui-même. Et aussi le protocole est mis en œuvre dans la classe d'en-tête.
@interface viewController: UIViewController <ServiceResponceDelegate>
{
ServiceClass* _service;
}
- (void) go;
@end
@implementation viewController
//
//some methods
//
- (void) go
{
_service = [[ServiceClass alloc] init];
[_service setDelegate:self];
[_service someTask];
}
Ca y est, et en mettant en œuvre des méthodes de délégués dans cette classe, le contrôle va revenir une fois l'opération / tâche est accomplie.
Avertissement: ceci est la Swiftversion de la façon de créer un delegate.
Alors, quels sont les délégués? ... dans le développement de logiciels, il existe des architectures de solutions réutilisables générales qui aident à résoudre les problèmes fréquemment rencontrés dans un contexte donné, ces « modèles », pour ainsi dire, sont mieux connus comme modèles de conception. Les délégués sont un modèle de conception qui permet à un objet d'envoyer des messages à un autre objet lorsqu'un événement particulier se produit. Imaginez un objet A appelle un B pour effectuer une action d'objet. Une fois l'action terminée, l'objet A devrait savoir que B a terminé la tâche et de prendre les mesures nécessaires, cela peut être réalisé avec l'aide des délégués!
Pour une meilleure explication, je vais vous montrer comment créer un délégué personnalisé qui transmet des données entre les classes, avec Swift dans une application simple, commencez par le téléchargement ou le clonage de ce projet de démarrage et l' exécuter!
Vous pouvez voir une application avec deux classes, ViewController Aet ViewController B. B a deux points de vue que le robinet change la couleur de fond de la ViewController, rien droit trop compliqué? bien songeons maintenant un moyen facile de changer aussi la couleur de fond de la classe A quand les vues sur la classe B sont taraudés.
Le problème est que ce point de vue font partie de la classe B et ont aucune idée de la classe A, donc nous avons besoin de trouver un moyen de communiquer entre ces deux classes, et c'est là resplendit la délégation. Je partageais la mise en œuvre en 6 étapes afin que vous puissiez l'utiliser comme une feuille de triche quand vous en avez besoin.
Étape 1: Recherchez l'étape de marque pragma 1 dans le fichier ClassBVC et ajoutez cette
//MARK: step 1 Add Protocol here.
protocol ClassBVCDelegate: class {
func changeBackgroundColor(_ color: UIColor?)
}
La première étape consiste à créer un protocol, dans ce cas, nous allons créer le protocole en classe B, à l' intérieur du protocole que vous pouvez créer autant de fonctions que vous souhaitez en fonction des exigences de votre mise en œuvre. Dans ce cas, nous avons juste une fonction simple qui accepte une option UIColorcomme argument. Est -ce une bonne pratique pour nommer vos protocoles ajoutant le mot delegateà la fin du nom de la classe, dans ce cas, ClassBVCDelegate.
Étape 2: Recherchez la marque pragma étape 2 ClassVBCet ajouter cette
//MARK: step 2 Create a delegate property here.
weak var delegate: ClassBVCDelegate?
Ici , nous venons de créer une propriété de délégué pour la classe, cette propriété doit adopter le protocoltype et il devrait être en option. En outre, vous devez ajouter le mot - clé faible avant la propriété pour éviter de conserver les cycles et les fuites de mémoire potentiels, si vous ne savez pas ce que cela signifie ne vous inquiétez pas pour l' instant, n'oubliez pas d'ajouter ce mot - clé.
Étape 3: Recherchez l'étape de marque pragma 3 à l' intérieur du handleTap methoddans ClassBVCet ajoutez cette
//MARK: step 3 Add the delegate method call here.
delegate?.changeBackgroundColor(tapGesture.view?.backgroundColor)
Une chose que vous devez savoir, exécutez l'application et appuyez sur une vue, vous ne verrez aucun nouveau comportement et c'est correct , mais la chose que je tiens à souligner est que l'application ce n'est pas écraser lorsque le délégué est appelé, et c'est parce que nous créons comme une valeur facultative et c'est la raison pour laquelle il ne plantera pas même le n'existe pas encore délégué. Allons maintenant ClassAVCdéposer et de le rendre, le délégué.
Étape 4: Cherchez l'étape de la marque de 4 pragma dans la méthode de handleTap dans ClassAVCet ajoutez ce à côté de votre type de classe comme celui - ci.
//MARK: step 4 conform the protocol here.
class ClassAVC: UIViewController, ClassBVCDelegate {
}
Maintenant ClassAVC a adopté le ClassBVCDelegateprotocole, vous pouvez voir que votre compilateur vous donne une erreur qui dit « Type « ClassAVC ne se conforme pas au protocole « ClassBVCDelegate » et cela signifie seulement que vous n'avez pas utilisé encore les méthodes du protocole, imaginez que lorsque la classe a adopte le protocole est comme la signature d' un contrat avec la classe B et ce contrat dit « Toute classe me adoptant doit absolument être mes fonctions! »
Note rapide: Si vous venez d'un Objective-Carrière - plan que vous pensez probablement que vous pouvez aussi fermer cette erreur rendant cette méthode facultative, mais pour ma grande surprise, et probablement la vôtre, la Swiftlangue ne prend pas en charge en option protocols, si vous voulez le faire , vous pouvez créer une extension pour votre protocolou utiliser le mot - clé @objc dans votre protocolmise en œuvre.
Personnellement, si je dois créer un protocole avec différentes méthodes en option , je préférerais le casser en différents protocols, de cette façon , je vais suivre le concept de donner une responsabilité unique à mes objets, mais elle peut varier en fonction de la mise en œuvre spécifique.
voici un bon article sur les méthodes en option.
Étape 5: Recherchez l'étape de marque pragma 5 dans la préparation pour la méthode de Segue et ajoutez cette
//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
}
Ici , nous sommes juste en train de créer une instance de ClassBVCet attribuons son délégué à soi - même, mais ce qui est moi ici? bien, l' auto est ce ClassAVCqui a été délégué!
Étape 6: Enfin, recherchez l'étape de pragma 6 ClassAVCet nous allons utiliser les fonctions du protocol, commencez à taper func changeBackgroundColor et vous verrez qu'il est auto-remplir pour vous. Vous pouvez ajouter une mise en œuvre à l' intérieur, dans cet exemple, nous allons simplement changer la couleur d'arrière - plan, ajoutez.
//MARK: step 6 finally use the method of the contract
func changeBackgroundColor(_ color: UIColor?) {
view.backgroundColor = color
}
Maintenant, exécutez l'application!
Delegatessont partout et vous les utilisez probablement sans même remarquer, si vous créez un tableviewdans le passé que vous avez utilisé la délégation, de nombreuses classes d' UIKITœuvres autour d' eux et beaucoup d' autres frameworksaussi, ils résolvent ces problèmes principaux.
Félicitations, vous mettre en œuvre juste un délégué personnalisé, je sais que vous pensez probablement, tant de peine juste pour cela? bien, la délégation est un modèle de conception très important de comprendre si vous voulez devenir un iOSdéveloppeur, et toujours garder à l' esprit qu'ils ont relation biunivoque entre les objets.
Vous pouvez voir le tutoriel d' origine ici
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;
Méthode:
-(void)delegateMEthod: (ArgType) arg{
}
Réponse est en fait répondu, mais je voudrais vous donner un pour la création d'un délégué « antisèche »:
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
Commençons par un exemple, si nous achetons un produit en ligne, il passe par le processus comme expédition / livraison assurée par différents teams.So si l'expédition se terminé, l'équipe d'expédition doit en informer l'équipe de livraison et il devrait être de une à une communication que la diffusion de ces informations serait en tête pour les autres / fournisseur pourrait vouloir transmettre cette information uniquement aux personnes nécessaires.
Donc, si nous pensons en termes de notre application, un événement peut être une commande en ligne et des équipes différentes peuvent être vues comme plusieurs.
Voici le code en tant qu'équipe ShippingView envisager Expédition & DeliveryView que l'équipe de livraison:
//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
//
}
}
À mon point de vue créer une catégorie distincte pour cette méthode déléguée et vous pouvez utiliser où vous voulez.
dans ma mesure 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;
après ce fichier in.m créer une matrice avec des objets,
- (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];
}
}
}];
}
Ici, tous sont définis pour délégué personnalisé class.after que vous pouvez utiliser cette méthode déléguée où vous want.for exemple ...
dans mon autre importation viewcontroller après
créer une action pour appeler la méthode des délégués comme celui-ci
- (IBAction)dropDownBtn1Action:(id)sender {
DropDownViewController *vehicleModelDropView = [[DropDownViewController alloc]init];
vehicleModelDropView.dropDownType = DDCITY;
vehicleModelDropView.delegate = self;
[self presentViewController:vehicleModelDropView animated:YES completion:nil];
}
après cette méthode de délégué d'appel comme celui-ci
- (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. Mettre en œuvre la méthode dans la classe .m - (void) didRemoveCellWithTag: (NSInteger) balise {@ NSLog ( "Tag% d", étiquette);
}
Délégué: - Créer
@protocol addToCartDelegate <NSObject>
-(void)addToCartAction:(ItemsModel *)itemsModel isAdded:(BOOL)added;
@end
Envoyer et s'il vous plaît assigner délégué à la vue que vous envoyez des données
[self.delegate addToCartAction:itemsModel isAdded:YES];