Un délégué Objective-C est un objet qui a été affecté à la delegatepropriété un autre objet. Pour en créer une, vous définissez une classe qui implémente les méthodes déléguées qui vous intéressent et marquez cette classe comme implémentant le protocole délégué.
Par exemple, supposons que vous ayez un UIWebView. Si vous souhaitez implémenter la webViewDidStartLoad:méthode de son délégué , vous pouvez créer une classe comme celle-ci:
Sur le UIWebViewcôté, il a probablement un code similaire à celui-ci pour voir si le délégué répond au webViewDidStartLoad:message en utilisant respondsToSelector:et l'envoyer le cas échéant.
La propriété déléguée elle-même est généralement déclarée weak(dans ARC) ou assign(pré-ARC) pour éviter de conserver les boucles, car le délégué d'un objet détient souvent une référence forte à cet objet. (Par exemple, un contrôleur de vue est souvent le délégué d'une vue qu'il contient.)
Faire des délégués pour vos cours
Pour définir vos propres délégués, vous devrez déclarer leurs méthodes quelque part, comme indiqué dans les documents Apple sur les protocoles . Vous déclarez généralement un protocole formel. La déclaration, paraphrasée de UIWebView.h, ressemblerait à ceci:
@protocolUIWebViewDelegate<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. Les exécutants délégués devraient adopter ce protocole:
@interfaceMyClass<UIWebViewDelegate>// ...@end
Et puis implémentez les méthodes dans le protocole. Pour les méthodes déclarées dans le protocole comme @optional(comme la plupart des méthodes déléguées), vous devez vérifier avec -respondsToSelector:avant d'appeler une méthode particulière dessus.
Appellation
Les méthodes déléguées sont généralement nommées en commençant par le nom de la classe délégante et prennent l'objet délégué comme premier paramètre. Ils utilisent aussi souvent un testament, un devoir ou un didacticiel. Ainsi, webViewDidStartLoad:(le premier paramètre est la vue Web) plutôt que loadStarted(en ne prenant aucun paramètre) par exemple.
Optimisations de vitesse
Au lieu de vérifier si un délégué répond à un sélecteur chaque fois que nous voulons lui envoyer un message, vous pouvez mettre en cache ces informations lorsque les délégués sont définis. Une façon très simple de le faire est d'utiliser un champ de bits, comme suit:
Ensuite, dans le corps, nous pouvons vérifier que notre délégué gère les messages en accédant à notre delegateRespondsTostructure, plutôt qu'en envoyant -respondsToSelector:encore et encore.
Délégués informels
Avant l'existence des protocoles, il était courant d'utiliser une catégorie sur NSObjectpour déclarer les méthodes qu'un délégué pouvait implémenter. Par exemple, fait CALayertoujours ceci:
@interfaceNSObject(CALayerDelegate)-(void)displayLayer:(CALayer*)layer;// ... other methods here@end
Cela indique au compilateur que tout objet peut implémenter displayLayer:.
Vous utiliseriez alors la même -respondsToSelector:approche que celle décrite ci-dessus pour appeler cette méthode. Les délégués implémentent cette méthode et assignent la delegatepropriété, et c'est tout (il n'y a pas de déclaration de conformité à un protocole). Cette méthode est courante dans les bibliothèques d'Apple, mais le nouveau code devrait utiliser l'approche de protocole plus moderne ci-dessus, car cette approche pollue NSObject(ce qui rend la saisie semi-automatique moins utile) et rend difficile pour le compilateur de vous avertir des fautes de frappe et des erreurs similaires.
Je pense que vous devez convertir le unsigned inttype en BOOLtant que la valeur de retour de delegate respondsToSelectorest de type BOOL.
Roland
Le délégué peut-il être utilisé pour le polymorphisme comme en C ++?
@Dan Oui, bien sûr. Les protocoles en général sont utilisés pour le polymorphisme.
Jesse Rusak
@JesseRusak Je pense que "JSSomethingDelegate" devrait être "SomethingDelegate" pour plus de cohérence :)
Hans Knöchel
382
La réponse approuvée est excellente, mais si vous cherchez une réponse d'une minute, essayez ceci:
Le fichier MyClass.h devrait ressembler à ceci (ajoutez des lignes de délégué avec des commentaires!)
#import <BlaClass/BlaClass.h>@classMyClass;//define class, so protocol can see MyClass@protocolMyClassDelegate<NSObject>//define delegate protocol-(void) myClassDelegateMethod:(MyClass*) sender;//define delegate method to be implemented within another class@end//end protocol@interfaceMyClass:NSObject{}@property(nonatomic, weak) id <MyClassDelegate>delegate;//define MyClassDelegate as delegate@end
Le fichier MyClass.m devrait ressembler à ceci
#import "MyClass.h"@implementationMyClass@synthesizedelegate;//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"@interfaceMyVC:UIViewController<MyClassDelegate>{//make it a delegate for MyClassDelegate}
MyVC.m:
myClass.delegate= self;//set its delegate to self somewhere
Implémenter la méthode déléguée
-(void) myClassDelegateMethod:(MyClass*) sender {NSLog(@"Delegates are great!");}
Super d'utiliser cette réponse comme référence rapide. Mais pourquoi la propriété déléguée de votre MyClass.h est-elle marquée comme «IBOutlet»?
Arno van der Meer
4
@ArnovanderMeer Bonne prise! Je ne me souviens pas pourquoi. J'en ai besoin dans mon projet mais pas dans cet exemple, je l'ai supprimé. thx
Tibidabo
Merci. Aussi agréable et approfondie que soit la réponse acceptée, j'apprends mieux à partir d'un exemple de code compact. C'est bien d'avoir deux réponses.
sudo
@Tibidabo Totalement exceptionnel. Je souhaite vraiment que tout le monde puisse expliquer des concepts de programmation comme celui-ci. J'ai vu des centaines d'explications, au sujet des «délégués», au fil des ans et je n'ai jamais vraiment saisi cette théorie jusqu'à présent! Merci beaucoup ...
Charles Robertson
5
Où est myClassinstancié dans MyVC.m?
Lane Rettig
18
Lors de l'utilisation de la méthode de protocole formelle pour créer la prise en charge des délégués, j'ai constaté que vous pouvez garantir une vérification de type appropriée (bien que, au moment de l'exécution, pas de temps de compilation) 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 d'accesseur délégué (setDelegate). Cela permet de minimiser les erreurs.
C'est peut-être plus dans le sens de ce qui vous manque:
Si vous venez d'un point de vue similaire à C ++, les délégués prennent un peu de temps pour s'y habituer - mais en gros 'ils fonctionnent juste'.
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é possibles. Donc, quelque chose se passe et NSWindowveut appeler votre objet - il utilise simplement la méthode d'Objective-c respondsToSelectorpour déterminer si votre objet veut que cette méthode soit appelée, puis l'appelle. Voici comment fonctionne objective-c - les méthodes sont recherchées à la demande.
C'est totalement trivial de le faire avec vos propres objets, il n'y a rien de spécial, vous pouvez par exemple avoir un NSArraydes 27 objets, toutes sortes d'objets, seulement 18 certains ayant la méthode -(void)setToBue;Les 9 autres n'en ont pas. Donc, pour appeler setToBluetous les 18 qui en ont besoin, quelque chose comme ceci:
for(id anObject in myArray){if([anObject respondsToSelector:@selector(@"setToBlue")])[anObject setToBlue];}
L'autre chose à propos des délégués est qu'ils ne sont pas conservés, vous devez donc toujours définir le délégué nildans votre MyClass deallocméthode.
En tant que bonne pratique recommandée par Apple, il est bon que le délégué (qui est un protocole, par définition), se conforme au NSObjectprotocole.
@protocolMyDelegate<NSObject>...@end
& pour créer des méthodes facultatives au sein de votre délégué (c'est-à-dire des méthodes qui ne doivent pas nécessairement être implémentées), vous pouvez utiliser l' @optionalannotation comme ceci:
@protocolMyDelegate<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
Ainsi, lorsque vous utilisez des méthodes que vous avez spécifiées comme facultatives, vous devez (dans votre classe) vérifier respondsToSelectorsi la vue (conforme à votre délégué) a réellement mis en œuvre votre ou vos méthodes facultatives.
Je pense que toutes ces réponses ont beaucoup de sens une fois que vous comprenez les délégués. Personnellement, je viens du pays du C / C ++ et avant cela, des langages procéduraux comme Fortran, etc. voici donc mon avis de 2 minutes sur la recherche d'analogues similaires dans le paradigme C ++.
Si je devais expliquer les délégués à un programmeur C ++ / Java, je dirais
Que sont les délégués? Ce sont des pointeurs statiques vers des classes d'une autre classe. Une fois que vous avez affecté un pointeur, vous pouvez appeler des fonctions / méthodes dans cette classe. Par conséquent, certaines fonctions de votre classe sont «déléguées» (dans le monde C ++ - pointeur vers par un pointeur d'objet de classe) vers une autre classe.
Quels sont les protocoles? Sur le plan conceptuel, il sert un objectif similaire au fichier d'en-tête de la classe que vous affectez en tant que classe déléguée. Un protocole est un moyen explicite de définir quelles méthodes doivent être implémentées dans la classe dont le pointeur a été défini comme 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 le feriez en définissant des pointeurs vers des classes (objets) dans la définition de classe, puis en les câblant à 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 maintenu dans le code et sera maladroit et sujet aux erreurs. Objective C suppose simplement que les programmeurs ne sont pas les meilleurs pour maintenir cette discipline et fournit des restrictions de compilation pour appliquer une implémentation propre.
Vous parlez de sémantique alors que je parlais de l'intuition. Ce dont vous parlez, c'est de la fonction virtuelle - mais juste pour vous habituer à la nouvelle terminologie peut être difficile. La réponse sert les débutants qui veulent penser à une parallèle dans C ++ / C
DrBug
Ce que vous dites n'est pas vraiment clair pour moi. Pourquoi n'écrivez-vous pas une nouvelle réponse et laissez-vous voir si plus de gens la trouvent utile, ils la voteront?
DrBug
9
Version Swift
Un délégué n'est qu'une classe qui travaille pour une autre classe. Lisez le code suivant pour un exemple de Playground quelque peu stupide (mais avec un peu de chance) qui montre comment cela est 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}classBossyBigBrother{// 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.returndelegate?.getYourNiceOlderSiblingAGlassOfWater()}}// PoorLittleSister conforms to the OlderSiblingDelegate protocolclassPoorLittleSister: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
Quand une classe doit communiquer des informations à une autre classe
Quand une classe veut autoriser une autre classe à la personnaliser
Les classes n'ont pas besoin de se connaître au préalable, sauf que la classe déléguée est conforme au protocole requis.
Je recommande fortement de lire les deux articles suivants. Ils m'ont aidé à mieux comprendre les délégués que la documentation .
D'accord, ce n'est pas vraiment une réponse à la question, mais si vous cherchez à faire votre propre délégué, peut-être que quelque chose de beaucoup plus simple pourrait être une meilleure réponse pour vous.
J'implémente à peine mes délégués car j'en ai rarement besoin. Je ne peux avoir qu'UN délégué pour un objet délégué. Donc, si vous voulez que votre délégué communique ou transmette des données à sens unique, vous êtes bien meilleur avec les notifications.
NSNotification peut transmettre des objets à plusieurs destinataires et il est très facile à utiliser. Cela fonctionne comme ceci:
Le fichier MyClass.m devrait ressembler à ceci
#import "MyClass.h"@implementationMyClass-(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 une autre classe: Ajoutez une classe en tant qu'observateur:
-(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 wantNSArray*otherClassData =[note userInfo][@"myClassData"];//get myClass data object and do whatever you want with it}
N'oubliez pas de retirer votre classe en tant qu'observateur si
disons que vous avez une classe que vous avez développée et que vous souhaitez déclarer une propriété déléguée pour pouvoir la notifier lorsqu'un événement se produit:
vous déclarez donc un protocole dans le MyClassfichier d' en- tête (ou un fichier d'en-tête séparé), déclarez les gestionnaires d'événements requis / facultatifs que votre délégué doit / devrait implémenter, puis déclarez une propriété dans MyClassde type ( id< MyClassDelegate>) qui signifie toute classe c objective conforme à le protocole MyClassDelegate, vous remarquerez que la propriété delegate est déclarée faible, ceci est très important pour empêcher le cycle de conservation (le plus souvent, le délégué conserve l' MyClassinstance donc si vous avez déclaré le délégué comme retenue, les deux se conserveront et aucun d'entre eux seront jamais publiés).
vous remarquerez également que les méthodes de protocole transmettent l' MyClassinstance au délégué en tant que paramètre, c'est la meilleure pratique dans le cas où le délégué souhaite appeler certaines méthodes sur l' MyClassinstance et aide également lorsque le délégué se déclare quant MyClassDelegateà plusieurs MyClassinstances, comme lorsque vous en avez plusieurs UITableView'sinstances dans votre ViewControlleret se déclare comme un UITableViewDelegateà tous.
et à l'intérieur de votre, MyClassvous notifiez le délégué avec les événements déclarés comme suit:
vous vérifiez d'abord 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 l'implémenterait pas et l'application se bloquerait alors (même si la méthode de protocole est requise).
Créez le protocole dans le fichier .h. Assurez-vous qu'il est défini avant le protocole à l'aide de @class suivi du nom de UIViewController< As the protocol I am going to use is UIViewController class>.
Étape: 1: Créez un nouveau protocole de classe nommé "YourViewController" qui sera la sous-classe de la classe UIViewController et affectez cette classe au deuxième ViewController.
Étape: 2: Accédez au fichier "YourViewController" et modifiez-le comme ci-dessous:
#import <UIKit/UIkit.h>@classYourViewController;@protocolYourViewControllerDelegate<NSObject>@optional-(void)defineDelegateMethodName:(YourViewController*) controller;@required-(BOOL)delegateMethodReturningBool:(YourViewController*) controller;@end@interfaceYourViewController: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<YourViewControllerDelegate>delegate;@end
Les méthodes définies dans le comportement du protocole peuvent être contrôlées avec @optional et @required dans le cadre de la définition du protocole.
Étape: 3: Mise en œuvre du délégué
#import "delegate.h"@interfaceYourDelegateUser()<YourViewControllerDelegate>@end@implementationYourDelegateUser-(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 herereturn YES;}@end
// teste si la méthode a été définie avant de l'appeler
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 implémenter. Et puis implémentez ce protocole dans votre classe d'en-tête où vous souhaitez implémenter le délégué ou les méthodes de délégué.
Il s'agit de la classe de service où une tâche doit être effectuée. Il montre comment définir un délégué et comment définir le délégué. Dans la classe d'implémentation, une fois la tâche terminée, les méthodes du délégué sont appelées.
Il s'agit de la classe de vue principale à partir de laquelle la classe de service est appelée en définissant le délégué sur lui-même. Et le protocole est également implémenté dans la classe d'en-tête.
Avertissement: il s'agit de la Swiftversion de la création d'un fichier delegate.
Alors, quels sont les délégués? … Dans le développement de logiciels, il existe des architectures de solutions générales réutilisables qui aident à résoudre les problèmes courants dans un contexte donné, ces «modèles», pour ainsi dire, sont mieux connus sous le nom de 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 spécifique se produit. Imaginez un objet A appelle un objet B pour effectuer une action. Une fois l'action terminée, l'objet A doit savoir que B a terminé la tâche et prendre les mesures nécessaires, cela peut être réalisé avec l'aide des délégués!
Vous pouvez voir une application avec deux classes, ViewController Aet ViewController B. B a deux vues qui au toucher modifient la couleur d'arrière-plan du ViewController, rien de trop compliqué non? Eh bien, réfléchissons maintenant de manière simple à la couleur d'arrière-plan de la classe A lorsque les vues sur la classe B sont exploitées.
Le problème est que ces vues font partie de la classe B et n'ont aucune idée de la classe A, nous devons donc trouver un moyen de communiquer entre ces deux classes, et c'est là que la délégation brille. J'ai divisé l'implémentation en 6 étapes afin que vous puissiez l'utiliser comme une feuille de triche lorsque vous en avez besoin.
étape 1: recherchez la marque pragma étape 1 dans le fichier ClassBVC et ajoutez-la
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, vous pouvez créer autant de fonctions que vous le souhaitez en fonction des exigences de votre implémentation. Dans ce cas, nous avons juste une fonction simple qui accepte une option UIColorcomme argument. Est une bonne pratique pour nommer vos protocoles en ajoutant le mot delegateà la fin du nom de la classe, dans ce cas ClassBVCDelegate,.
étape 2: recherchez la marque pragma étape 2 ClassVBCet ajoutez-la
//MARK: step 2 Create a delegate property here.
weak var delegate:ClassBVCDelegate?
Ici, nous venons de créer une propriété déléguée pour la classe, cette propriété doit adopter le protocoltype et elle doit être facultative. 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 potentielles.Si vous ne savez pas ce que cela signifie, ne vous inquiétez pas pour le moment, n'oubliez pas d'ajouter ce mot clé.
Étape 3: Recherchez la marque pragma étape 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 n'importe quelle vue, vous ne verrez aucun nouveau comportement et c'est correct, mais la chose que je veux souligner est que l'application ne se bloque pas lorsque le délégué est appelé, et c'est parce que nous le créons en tant que valeur facultative et c'est pourquoi il ne plantera pas même le délégué n'existe pas encore. Allons maintenant au ClassAVCfichier et le faire, le délégué.
étape 4: recherchez la marque de pragma étape 4 dans la méthode handleTap ClassAVCet ajoutez-la à côté de votre type de classe comme ceci.
//MARK: step 4 conform the protocol here.classClassAVC:UIViewController,ClassBVCDelegate{}
Maintenant ClassAVC a adopté le ClassBVCDelegateprotocole, vous pouvez voir que votre compilateur vous donne une erreur qui dit "Type" ClassAVC n'est pas conforme au protocole "ClassBVCDelegate" et cela signifie seulement que vous n'avez pas encore utilisé les méthodes du protocole, imaginez que quand la classe A adopte le protocole, c'est comme signer un contrat avec la classe B et ce contrat dit "Toute classe qui m'adopte DOIT utiliser mes fonctions!"
Remarque rapide: si vous venez d'un Objective-Carrière-plan, vous pensez probablement que vous pouvez également fermer cette erreur en rendant cette méthode facultative, mais à ma grande surprise, et probablement la vôtre, le Swiftlangage ne prend pas en charge facultatif protocols, si vous voulez le faire, vous pouvez créer une extension pour votre protocolou utilisez le mot clé @objc dans votre protocolimplémentation.
Personnellement, si je dois créer un protocole avec différentes méthodes optionnelles, je préférerais le diviser en différents protocols, de cette façon je suivrai le concept de donner une seule responsabilité à mes objets, mais cela peut varier en fonction de l'implémentation spécifique.
voici un bon article sur les méthodes optionnelles.
étape 5: recherchez la marque de pragma étape 5 à l'intérieur de la méthode de préparation à la séquence et ajoutez-la
//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 créons simplement une instance de ClassBVCet affectons son délégué à soi, mais qu'est-ce que le moi ici? eh bien, c'est soi ClassAVCqui a été délégué!
étape 6: Enfin, recherchez le pragma étape 6 dans ClassAVCet utilisons les fonctions de la protocol, commencez à taper func changeBackgroundColor et vous verrez qu'il le remplit automatiquement pour vous. Vous pouvez ajouter n'importe quelle implémentation à l'intérieur, dans cet exemple, nous allons simplement changer la couleur d'arrière-plan, ajoutez ceci.
//MARK: step 6 finally use the method of the contract
func changeBackgroundColor(_ color:UIColor?){
view.backgroundColor = color
}
Maintenant, lancez l'application!
Delegatessont partout et vous les utilisez probablement sans même avis, si vous créez une tableviewdélégation dans le passé, vous avez utilisé de nombreuses classes d' UIKITœuvres autour d'eux et bien d'autres frameworksaussi, ils résolvent ces principaux problèmes.
Évitez les couplages serrés d'objets.
Modifiez le comportement et l'apparence sans avoir besoin de sous-classer les objets.
Autorisez le traitement des tâches vers n'importe quel objet arbitraire.
Félicitations, vous venez d'implémenter un délégué personnalisé, je sais que vous pensez probablement, tant de mal juste pour ça? eh bien, la délégation est un modèle de conception très important pour comprendre si vous voulez devenir iOSdéveloppeur, et gardez toujours à l'esprit qu'ils ont une relation un à un entre les objets.
La réponse est en fait répondue, mais je voudrais vous donner une "feuille de triche" pour créer un délégué:
DELEGATE SCRIPT
CLASS A -Wheredelegate is calling function
@protocol<#ProtocolName#> <NSObject>-(void)delegateMethod;@end@interface<#SomeViewController#> : <#UIViewController#> @property(nonatomic, assign) id <<#ProtocolName#>> delegate;@end@implementation<#SomeViewController#> -(void)someMethod {[self.delegate methodName];}@end
CLASS B -Wheredelegate is called
@interface<#OtherViewController#> (<#Delegate Name#>) {}@end@implementation<#OtherViewController#> -(void)otherMethod {
CLASSA *classA =[[CLASSA alloc] init];[classA setDelegate:self];}-delegateMethod(){}@end
Ici, tous sont définis pour la classe déléguée personnalisée.Après cela, vous pouvez utiliser cette méthode déléguée où vous le souhaitez.Par exemple ...
dans mon autre importation de viewcontroller après cela
créer une action pour appeler la méthode déléguée comme celle-ci
après cette méthode d'appel délégué 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@interfaceMyClassUsesDelegate()<TB_RemovedUserCellTag>@end
// 5. Implémentez la méthode dans la classe .m - (void) didRemoveCellWithTag: (NSInteger) tag {NSLog @ ("Tag% d", tag);
Commençons par un exemple, si nous achetons un produit en ligne, il passe par un processus tel que l'expédition / la livraison géré par différentes équipes. serait une surcharge pour d'autres personnes / le fournisseur pourrait vouloir transmettre ces informations uniquement aux personnes requises.
Donc, si nous pensons en termes de notre application, un événement peut être une commande en ligne et différentes équipes peuvent être comme des vues multiples.
Voici le code considérer ShippingView comme équipe d'expédition et DeliveryView comme é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 productsclassShippingView:UIView{
weak var delegate:ShippingDelegate?
var productID :String@IBAction func checkShippingStatus(sender:UIButton){// if product is shippeddelegate?.productShipped(productID: productID)}}//Delivery view which shows delivery status & tracking infoclassDeliveryView: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 statusclassProductViewController: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
//}}
Réponses:
Un délégué Objective-C est un objet qui a été affecté à la
delegate
propriété un autre objet. Pour en créer une, vous définissez une classe qui implémente les méthodes déléguées qui vous intéressent et marquez cette classe comme implémentant le protocole délégué.Par exemple, supposons que vous ayez un
UIWebView
. Si vous souhaitez implémenter lawebViewDidStartLoad:
méthode de son délégué , vous pouvez créer une classe comme celle-ci:Ensuite, vous pouvez créer une instance de MyClass et l'affecter en tant que délégué de la vue Web:
Sur le
UIWebView
côté, il a probablement un code similaire à celui-ci pour voir si le délégué répond auwebViewDidStartLoad:
message en utilisantrespondsToSelector:
et l'envoyer le cas échéant.La propriété déléguée elle-même est généralement déclarée
weak
(dans ARC) ouassign
(pré-ARC) pour éviter de conserver les boucles, car le délégué d'un objet détient souvent une référence forte à cet objet. (Par exemple, un contrôleur de vue est souvent le délégué d'une vue qu'il contient.)Faire des délégués pour vos cours
Pour définir vos propres délégués, vous devrez déclarer leurs méthodes quelque part, comme indiqué dans les documents Apple sur les protocoles . Vous déclarez généralement un protocole formel. La déclaration, paraphrasée de UIWebView.h, ressemblerait à ceci:
Ceci est analogue à une interface ou à une classe de base abstraite, car elle crée un type spécial pour votre délégué,
UIWebViewDelegate
dans ce cas. Les exécutants délégués devraient adopter ce protocole:Et puis implémentez les méthodes dans le protocole. Pour les méthodes déclarées dans le protocole comme
@optional
(comme la plupart des méthodes déléguées), vous devez vérifier avec-respondsToSelector:
avant d'appeler une méthode particulière dessus.Appellation
Les méthodes déléguées sont généralement nommées en commençant par le nom de la classe délégante et prennent l'objet délégué comme premier paramètre. Ils utilisent aussi souvent un testament, un devoir ou un didacticiel. Ainsi,
webViewDidStartLoad:
(le premier paramètre est la vue Web) plutôt queloadStarted
(en ne prenant aucun paramètre) par exemple.Optimisations de vitesse
Au lieu de vérifier si un délégué répond à un sélecteur chaque fois que nous voulons lui envoyer un message, vous pouvez mettre en cache ces informations lorsque les délégués sont définis. Une façon très simple de le faire est d'utiliser un champ de bits, comme suit:
Ensuite, dans le corps, nous pouvons vérifier que notre délégué gère les messages en accédant à notre
delegateRespondsTo
structure, plutôt qu'en envoyant-respondsToSelector:
encore et encore.Délégués informels
Avant l'existence des protocoles, il était courant d'utiliser une catégorie sur
NSObject
pour déclarer les méthodes qu'un délégué pouvait implémenter. Par exemple, faitCALayer
toujours ceci:Cela indique au compilateur que tout objet peut implémenter
displayLayer:
.Vous utiliseriez alors la même
-respondsToSelector:
approche que celle décrite ci-dessus pour appeler cette méthode. Les délégués implémentent cette méthode et assignent ladelegate
propriété, et c'est tout (il n'y a pas de déclaration de conformité à un protocole). Cette méthode est courante dans les bibliothèques d'Apple, mais le nouveau code devrait utiliser l'approche de protocole plus moderne ci-dessus, car cette approche pollueNSObject
(ce qui rend la saisie semi-automatique moins utile) et rend difficile pour le compilateur de vous avertir des fautes de frappe et des erreurs similaires.la source
unsigned int
type enBOOL
tant que la valeur de retour dedelegate respondsToSelector
est de typeBOOL
.La réponse approuvée est excellente, mais si vous cherchez une réponse d'une minute, essayez ceci:
Le fichier MyClass.h devrait ressembler à ceci (ajoutez des lignes de délégué avec des commentaires!)
Le fichier MyClass.m devrait ressembler à ceci
Pour utiliser votre délégué dans une autre classe (UIViewController appelé MyVC dans ce cas) MyVC.h:
MyVC.m:
Implémenter la méthode déléguée
la source
myClass
instancié dans MyVC.m?Lors de l'utilisation de la méthode de protocole formelle pour créer la prise en charge des délégués, j'ai constaté que vous pouvez garantir une vérification de type appropriée (bien que, au moment de l'exécution, pas de temps de compilation) en ajoutant quelque chose comme:
dans votre code d'accesseur délégué (setDelegate). Cela permet de minimiser les erreurs.
la source
S'il vous plaît! consultez le didacticiel simple étape par étape ci-dessous pour comprendre le fonctionnement des délégués dans iOS.
J'ai créé deux ViewControllers (pour envoyer des données de l'un à l'autre)
la source
C'est peut-être plus dans le sens de ce qui vous manque:
Si vous venez d'un point de vue similaire à C ++, les délégués prennent un peu de temps pour s'y habituer - mais en gros 'ils fonctionnent juste'.
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é possibles. Donc, quelque chose se passe et
NSWindow
veut appeler votre objet - il utilise simplement la méthode d'Objective-crespondsToSelector
pour déterminer si votre objet veut que cette méthode soit appelée, puis l'appelle. Voici comment fonctionne objective-c - les méthodes sont recherchées à la demande.C'est totalement trivial de le faire avec vos propres objets, il n'y a rien de spécial, vous pouvez par exemple avoir un
NSArray
des 27 objets, toutes sortes d'objets, seulement 18 certains ayant la méthode-(void)setToBue;
Les 9 autres n'en ont pas. Donc, pour appelersetToBlue
tous les 18 qui en ont besoin, quelque chose comme ceci:L'autre chose à propos des délégués est qu'ils ne sont pas conservés, vous devez donc toujours définir le délégué
nil
dans votreMyClass dealloc
méthode.la source
En tant que bonne pratique recommandée par Apple, il est bon que le délégué (qui est un protocole, par définition), se conforme au
NSObject
protocole.& pour créer des méthodes facultatives au sein de votre délégué (c'est-à-dire des méthodes qui ne doivent pas nécessairement être implémentées), vous pouvez utiliser l'
@optional
annotation comme ceci:Ainsi, lorsque vous utilisez des méthodes que vous avez spécifiées comme facultatives, vous devez (dans votre classe) vérifier
respondsToSelector
si la vue (conforme à votre délégué) a réellement mis en œuvre votre ou vos méthodes facultatives.la source
Je pense que toutes ces réponses ont beaucoup de sens une fois que vous comprenez les délégués. Personnellement, je viens du pays du C / C ++ et avant cela, des langages procéduraux comme Fortran, etc. voici donc mon avis de 2 minutes sur la recherche d'analogues similaires dans le paradigme C ++.
Si je devais expliquer les délégués à un programmeur C ++ / Java, je dirais
Que sont les délégués? Ce sont des pointeurs statiques vers des classes d'une autre classe. Une fois que vous avez affecté un pointeur, vous pouvez appeler des fonctions / méthodes dans cette classe. Par conséquent, certaines fonctions de votre classe sont «déléguées» (dans le monde C ++ - pointeur vers par un pointeur d'objet de classe) vers une autre classe.
Quels sont les protocoles? Sur le plan conceptuel, il sert un objectif similaire au fichier d'en-tête de la classe que vous affectez en tant que classe déléguée. Un protocole est un moyen explicite de définir quelles méthodes doivent être implémentées dans la classe dont le pointeur a été défini comme 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 le feriez en définissant des pointeurs vers des classes (objets) dans la définition de classe, puis en les câblant à 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 maintenu dans le code et sera maladroit et sujet aux erreurs. Objective C suppose simplement que les programmeurs ne sont pas les meilleurs pour maintenir cette discipline et fournit des restrictions de compilation pour appliquer une implémentation propre.
la source
Version Swift
Un délégué n'est qu'une classe qui travaille pour une autre classe. Lisez le code suivant pour un exemple de Playground quelque peu stupide (mais avec un peu de chance) qui montre comment cela est fait dans Swift.
Dans la pratique, les délégués sont souvent utilisés dans les situations suivantes
Les classes n'ont pas besoin de se connaître au préalable, sauf que la classe déléguée est conforme au protocole requis.
Je recommande fortement de lire les deux articles suivants. Ils m'ont aidé à mieux comprendre les délégués que la documentation .
la source
D'accord, ce n'est pas vraiment une réponse à la question, mais si vous cherchez à faire votre propre délégué, peut-être que quelque chose de beaucoup plus simple pourrait être une meilleure réponse pour vous.
J'implémente à peine mes délégués car j'en ai rarement besoin. Je ne peux avoir qu'UN délégué pour un objet délégué. Donc, si vous voulez que votre délégué communique ou transmette des données à sens unique, vous êtes bien meilleur avec les notifications.
NSNotification peut transmettre des objets à plusieurs destinataires et il est très facile à utiliser. Cela fonctionne comme ceci:
Le fichier MyClass.m devrait ressembler à ceci
Pour utiliser votre notification dans une autre classe: Ajoutez une classe en tant qu'observateur:
Implémentez le sélecteur:
N'oubliez pas de retirer votre classe en tant qu'observateur si
la source
disons que vous avez une classe que vous avez développée et que vous souhaitez déclarer une propriété déléguée pour pouvoir la notifier lorsqu'un événement se produit:
vous déclarez donc un protocole dans le
MyClass
fichier d' en- tête (ou un fichier d'en-tête séparé), déclarez les gestionnaires d'événements requis / facultatifs que votre délégué doit / devrait implémenter, puis déclarez une propriété dansMyClass
de type (id< MyClassDelegate>
) qui signifie toute classe c objective conforme à le protocoleMyClassDelegate
, vous remarquerez que la propriété delegate est déclarée faible, ceci est très important pour empêcher le cycle de conservation (le plus souvent, le délégué conserve l'MyClass
instance donc si vous avez déclaré le délégué comme retenue, les deux se conserveront et aucun d'entre eux seront jamais publiés).vous remarquerez également que les méthodes de protocole transmettent l'
MyClass
instance au délégué en tant que paramètre, c'est la meilleure pratique dans le cas où le délégué souhaite appeler certaines méthodes sur l'MyClass
instance et aide également lorsque le délégué se déclare quantMyClassDelegate
à plusieursMyClass
instances, comme lorsque vous en avez plusieursUITableView's
instances dans votreViewController
et se déclare comme unUITableViewDelegate
à tous.et à l'intérieur de votre,
MyClass
vous notifiez le délégué avec les événements déclarés comme suit:vous vérifiez d'abord 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 l'implémenterait pas et l'application se bloquerait alors (même si la méthode de protocole est requise).
la source
Voici une méthode simple pour créer des délégués
Créez le protocole dans le fichier .h. Assurez-vous qu'il est défini avant le protocole à l'aide de @class suivi du nom de UIViewController
< As the protocol I am going to use is UIViewController class>.
Étape: 1: Créez un nouveau protocole de classe nommé "YourViewController" qui sera la sous-classe de la classe UIViewController et affectez cette classe au deuxième ViewController.
Étape: 2: Accédez au fichier "YourViewController" et modifiez-le comme ci-dessous:
Les méthodes définies dans le comportement du protocole peuvent être contrôlées avec @optional et @required dans le cadre de la définition du protocole.
Étape: 3: Mise en œuvre du délégué
// teste si la méthode a été définie avant de l'appeler
la source
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 implémenter. Et puis implémentez ce protocole dans votre classe d'en-tête où vous souhaitez implémenter le délégué ou les méthodes de délégué.
Un protocole doit être déclaré comme suit:
Il s'agit de la classe de service où une tâche doit être effectuée. Il montre comment définir un délégué et comment définir le délégué. Dans la classe d'implémentation, une fois la tâche terminée, les méthodes du délégué sont appelées.
Il s'agit de la classe de vue principale à partir de laquelle la classe de service est appelée en définissant le délégué sur lui-même. Et le protocole est également implémenté dans la classe d'en-tête.
C'est tout, et en implémentant des méthodes déléguées dans cette classe, le contrôle reviendra une fois l'opération / tâche terminée.
la source
Avertissement: il s'agit de la
Swift
version de la création d'un fichierdelegate
.Alors, quels sont les délégués? … Dans le développement de logiciels, il existe des architectures de solutions générales réutilisables qui aident à résoudre les problèmes courants dans un contexte donné, ces «modèles», pour ainsi dire, sont mieux connus sous le nom de 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 spécifique se produit. Imaginez un objet A appelle un objet B pour effectuer une action. Une fois l'action terminée, l'objet A doit savoir que B a terminé la tâche et 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 passe des données entre les classes, avec Swift dans une application simple, commencez par télécharger ou cloner ce projet de démarrage et exécutez-le!
Vous pouvez voir une application avec deux classes,
ViewController A
etViewController B
. B a deux vues qui au toucher modifient la couleur d'arrière-plan duViewController
, rien de trop compliqué non? Eh bien, réfléchissons maintenant de manière simple à la couleur d'arrière-plan de la classe A lorsque les vues sur la classe B sont exploitées.Le problème est que ces vues font partie de la classe B et n'ont aucune idée de la classe A, nous devons donc trouver un moyen de communiquer entre ces deux classes, et c'est là que la délégation brille. J'ai divisé l'implémentation en 6 étapes afin que vous puissiez l'utiliser comme une feuille de triche lorsque vous en avez besoin.
étape 1: recherchez la marque pragma étape 1 dans le fichier ClassBVC et ajoutez-la
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, vous pouvez créer autant de fonctions que vous le souhaitez en fonction des exigences de votre implémentation. Dans ce cas, nous avons juste une fonction simple qui accepte une optionUIColor
comme argument. Est une bonne pratique pour nommer vos protocoles en ajoutant le motdelegate
à la fin du nom de la classe, dans ce casClassBVCDelegate
,.étape 2: recherchez la marque pragma étape 2
ClassVBC
et ajoutez-laIci, nous venons de créer une propriété déléguée pour la classe, cette propriété doit adopter le
protocol
type et elle doit être facultative. 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 potentielles.Si vous ne savez pas ce que cela signifie, ne vous inquiétez pas pour le moment, n'oubliez pas d'ajouter ce mot clé.Étape 3: Recherchez la marque pragma étape 3 à l' intérieur du handleTap
method
dansClassBVC
et ajoutez cetteUne chose que vous devez savoir, exécutez l'application et appuyez sur n'importe quelle vue, vous ne verrez aucun nouveau comportement et c'est correct, mais la chose que je veux souligner est que l'application ne se bloque pas lorsque le délégué est appelé, et c'est parce que nous le créons en tant que valeur facultative et c'est pourquoi il ne plantera pas même le délégué n'existe pas encore. Allons maintenant au
ClassAVC
fichier et le faire, le délégué.étape 4: recherchez la marque de pragma étape 4 dans la méthode handleTap
ClassAVC
et ajoutez-la à côté de votre type de classe comme ceci.Maintenant ClassAVC a adopté le
ClassBVCDelegate
protocole, vous pouvez voir que votre compilateur vous donne une erreur qui dit "Type" ClassAVC n'est pas conforme au protocole "ClassBVCDelegate" et cela signifie seulement que vous n'avez pas encore utilisé les méthodes du protocole, imaginez que quand la classe A adopte le protocole, c'est comme signer un contrat avec la classe B et ce contrat dit "Toute classe qui m'adopte DOIT utiliser mes fonctions!"Remarque rapide: si vous venez d'un
Objective-C
arrière-plan, vous pensez probablement que vous pouvez également fermer cette erreur en rendant cette méthode facultative, mais à ma grande surprise, et probablement la vôtre, leSwift
langage ne prend pas en charge facultatifprotocols
, si vous voulez le faire, vous pouvez créer une extension pour votreprotocol
ou utilisez le mot clé @objc dans votreprotocol
implémentation.Personnellement, si je dois créer un protocole avec différentes méthodes optionnelles, je préférerais le diviser en différents
protocols
, de cette façon je suivrai le concept de donner une seule responsabilité à mes objets, mais cela peut varier en fonction de l'implémentation spécifique.voici un bon article sur les méthodes optionnelles.
étape 5: recherchez la marque de pragma étape 5 à l'intérieur de la méthode de préparation à la séquence et ajoutez-la
Ici, nous créons simplement une instance de
ClassBVC
et affectons son délégué à soi, mais qu'est-ce que le moi ici? eh bien, c'est soiClassAVC
qui a été délégué!étape 6: Enfin, recherchez le pragma étape 6 dans
ClassAVC
et utilisons les fonctions de laprotocol
, commencez à taper func changeBackgroundColor et vous verrez qu'il le remplit automatiquement pour vous. Vous pouvez ajouter n'importe quelle implémentation à l'intérieur, dans cet exemple, nous allons simplement changer la couleur d'arrière-plan, ajoutez ceci.Maintenant, lancez l'application!
Delegates
sont partout et vous les utilisez probablement sans même avis, si vous créez unetableview
délégation dans le passé, vous avez utilisé de nombreuses classes d'UIKIT
œuvres autour d'eux et bien d'autresframeworks
aussi, ils résolvent ces principaux problèmes.Félicitations, vous venez d'implémenter un délégué personnalisé, je sais que vous pensez probablement, tant de mal juste pour ça? eh bien, la délégation est un modèle de conception très important pour comprendre si vous voulez devenir
iOS
développeur, et gardez toujours à l'esprit qu'ils ont une relation un à un entre les objets.Vous pouvez voir le tutoriel original ici
la source
La réponse est en fait répondue, mais je voudrais vous donner une "feuille de triche" pour créer un délégué:
la source
ViewController.h
ViewController.m
MainViewController.m
Méthode:
la source
À mon avis, créez une classe distincte pour cette méthode déléguée et vous pouvez l'utiliser où vous le souhaitez.
dans mon DropDownClass.h personnalisé
après ce fichier in.m créer un tableau avec des objets,
Ici, tous sont définis pour la classe déléguée personnalisée.Après cela, vous pouvez utiliser cette méthode déléguée où vous le souhaitez.Par exemple ...
dans mon autre importation de viewcontroller après cela
créer une action pour appeler la méthode déléguée comme celle-ci
après cette méthode d'appel délégué comme celui-ci
la source
Délégué: - Créer
Envoyez et veuillez affecter un délégué pour voir que vous envoyez des données
la source
// 5. Implémentez la méthode dans la classe .m - (void) didRemoveCellWithTag: (NSInteger) tag {NSLog @ ("Tag% d", tag);
}
la source
Commençons par un exemple, si nous achetons un produit en ligne, il passe par un processus tel que l'expédition / la livraison géré par différentes équipes. serait une surcharge pour d'autres personnes / le fournisseur pourrait vouloir transmettre ces informations uniquement aux personnes requises.
Donc, si nous pensons en termes de notre application, un événement peut être une commande en ligne et différentes équipes peuvent être comme des vues multiples.
Voici le code considérer ShippingView comme équipe d'expédition et DeliveryView comme équipe de livraison:
la source