Les delegates en swift?

Comment fait-on pour créer un délégué, à savoir NSUserNotificationCenterDelegate dans swift?

Ce n’est pas si différent de obj-c. Tout d’abord, vous devez spécifier le protocole dans votre déclaration de classe, comme suit:

 class MyClass: NSUserNotificationCenterDelegate 

La mise en œuvre ressemblera à ceci:

 // NSUserNotificationCenterDelegate implementation func userNotificationCenter(center: NSUserNotificationCenter, didDeliverNotification notification: NSUserNotification) { //implementation } func userNotificationCenter(center: NSUserNotificationCenter, didActivateNotification notification: NSUserNotification) { //implementation } func userNotificationCenter(center: NSUserNotificationCenter, shouldPresentNotification notification: NSUserNotification) -> Bool { //implementation return true } 

Bien sûr, vous devez définir le délégué. Par exemple:

 NSUserNotificationCenter.defaultUserNotificationCenter().delegate = self; 

Voici un petit aide sur les delegates entre deux contrôleurs de vue:

Étape 1: Créez un protocole dans UIViewController que vous allez supprimer / enverrez les données.

 protocol FooTwoViewControllerDelegate:class { func myVCDidFinish(_ controller: FooTwoViewController, text: Ssortingng) } 

Etape 2: Déclarez le délégué dans la classe d’envoi (c.-à-d. UIViewcontroller)

 class FooTwoViewController: UIViewController { weak var delegate: FooTwoViewControllerDelegate? [snip...] } 

Etape 3: Utilisez le délégué dans une méthode de classe pour envoyer les données à la méthode de réception, c’est-à-dire toute méthode qui adopte le protocole.

 @IBAction func saveColor(_ sender: UIBarButtonItem) { delegate?.myVCDidFinish(self, text: colorLabel.text) //assuming the delegate is assigned otherwise error } 

Étape 4: Adoptez le protocole dans la classe de réception

 class ViewController: UIViewController, FooTwoViewControllerDelegate { 

Étape 5: implémenter la méthode de délégué

 func myVCDidFinish(_ controller: FooTwoViewController, text: Ssortingng) { colorLabel.text = "The Color is " + text controller.navigationController.popViewController(animated: true) } 

Etape 6: Définissez le délégué dans le prepareForSegue:

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "mySegue" { let vc = segue.destination as! FooTwoViewController vc.colorSsortingng = colorLabel.text vc.delegate = self } } 

Et ça devrait marcher. Ceci est bien sûr juste des fragments de code, mais devrait vous donner l’idée. Pour une longue explication de ce code, vous pouvez aller sur mon blog ici:

segues et delegates

Si vous vous intéressez à ce qui se passe sous le capot avec un délégué, j’ai écrit ceci:

sous le capot avec des delegates

Les delegates m’ont toujours confondu jusqu’à ce que je réalise qu’un délégué n’est qu’une classe qui travaille pour un autre cours . C’est comme avoir quelqu’un d’autre pour faire le sale boulot pour vous que vous ne voulez pas faire vous-même.

J’ai écrit une petite histoire pour illustrer cela. Lisez-le dans un terrain de jeu si vous le souhaitez.

Il était une fois…

 // MARK: Background to the story // A protocol is like a list of rules that need to be followed. protocol OlderSiblingDelegate: class { // The following command (ie, method) must be obeyed by any // underling (ie, delegate) of the older sibling. func getYourNiceOlderSiblingAGlassOfWater() } // MARK: Characters in the story class BossyBigBrother { // I can make whichever little sibling is around at // the time be my delegate (ie, slave) weak var delegate: OlderSiblingDelegate? func tellSomebodyToGetMeSomeWater() { // The delegate is optional because even though // I'm thirsty, there might not be anyone nearby // that I can boss around. delegate?.getYourNiceOlderSiblingAGlassOfWater() } } // Poor little sisters have to follow (or at least acknowledge) // their older sibling's rules (ie, protocol) class PoorLittleSister: OlderSiblingDelegate { func getYourNiceOlderSiblingAGlassOfWater() { // Little sis follows the letter of the law (ie, protocol), // but no one said exactly how she had to respond. print("Go get it yourself!") } } // MARK: The Story // Big bro is laying on the couch watching basketball on TV. let bigBro = BossyBigBrother() // He has a little sister named Sally. let sally = PoorLittleSister() // Sally walks into the room. How convenient! Now big bro // has someone there to boss around. bigBro.delegate = sally // So he tells her to get him some water. bigBro.tellSomebodyToGetMeSomeWater() // Unfortunately no one lived happily ever after... // The end. 

En revue, il y a trois parties clés pour créer et utiliser le modèle de délégué.

  1. le protocole qui définit ce que le travailleur doit faire
  2. la classe de boss qui a une variable delegate, qu’elle utilise pour indiquer à la classe de travail quoi faire
  3. la classe de travail qui adopte le protocole et fait ce qui est requirejs

Vrai vie

En comparaison avec notre histoire Bossy Big Brother ci-dessus, les delegates sont souvent utilisés pour les applications pratiques suivantes:

  1. Communication : une classe doit envoyer des informations à une autre classe.
    • Exemple de code 1: envoi de données d’un contrôleur de vue à un autre
    • Exemple de code 2: envoi de texte d’un clavier personnalisé à un champ de texte
  2. Personnalisation : une classe veut autoriser une autre classe à la personnaliser.

La grande partie est que ces classes n’ont pas besoin de rien savoir les unes des autres à l’avance, sauf que la classe des delegates est conforme au protocole requirejs.

Je recommande fortement de lire les deux articles suivants. Ils m’ont aidé à mieux comprendre les delegates que la documentation .

  • Qu’est-ce que la délégation? – Un guide du développeur rapide
  • Comment fonctionne la délégation – Guide du développeur rapide

Une note de plus

Les delegates qui référencent d’autres classes qu’ils ne possèdent pas doivent utiliser le mot-clé weak pour éviter des cycles de référence forts. Voir cette réponse pour plus de détails.

J’ai eu quelques corrections à poster sur @MakeAppPie

Tout d’abord, lorsque vous créez un protocole de délégué, celui-ci doit être conforme au protocole de classe. Comme dans l’exemple ci-dessous.

 protocol ProtocolDelegate: class { func myMethod(controller:ViewController, text:Ssortingng) } 

Deuxièmement, votre délégué devrait être faible pour éviter de conserver le cycle.

 class ViewController: UIViewController { weak var delegate: ProtocolDelegate? } 

Enfin, vous êtes en sécurité car votre protocole est une valeur facultative. Cela signifie que son message “nil” ne sera pas envoyé à cette propriété. Il est similaire à l’instruction conditionnelle avec respondToselector dans objC mais ici vous avez tout en une seule ligne:

 if ([self.delegate respondsToSelector:@selector(myMethod:text:)]) { [self.delegate myMethod:self text:@"you Text"]; } 

Vous avez ci-dessus un exemple d’obj-C et ci-dessous vous avez un exemple rapide de son apparence.

 delegate?.myMethod(self, text:"your Text") 

Voici un aperçu que j’ai mis ensemble. Je me demandais la même chose et cela a aidé à améliorer ma compréhension. Ouvrez-la dans un Xcode Playground pour voir ce qui se passe.

 protocol YelpRequestDelegate { func getYelpData() -> AnyObject func processYelpData(data: NSData) -> NSData } class YelpAPI { var delegate: YelpRequestDelegate? func getData() { println("data being resortingeved...") let data: AnyObject? = delegate?.getYelpData() } func processYelpData(data: NSData) { println("data being processed...") let data = delegate?.processYelpData(data) } } class Controller: YelpRequestDelegate { init() { var yelpAPI = YelpAPI() yelpAPI.delegate = self yelpAPI.getData() } func getYelpData() -> AnyObject { println("getYelpData called") return NSData() } func processYelpData(data: NSData) -> NSData { println("processYelpData called") return NSData() } } var controller = Controller() 

DÉLÉGUÉS DANS SWIFT 2

J’explique avec l’exemple de Delegate avec deux viewControllers.Dans ce cas, SecondVC Object envoie des données au premier View Controller.

Déclaration de classe avec protocole

 protocol getDataDelegate { func getDataFromAnotherVC(temp: Ssortingng) } import UIKit class SecondVC: UIViewController { var delegateCustom : getDataDelegate? override func viewDidLoad() { super.viewDidLoad() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } @IBAction func backToMainVC(sender: AnyObject) { //calling method defined in first View Controller with Object self.delegateCustom?.getDataFromAnotherVC("I am sending data from second controller to first view controller.Its my first delegate example. I am done with custom delegates.") self.navigationController?.popViewControllerAnimated(true) } } 

Dans le premier protocole ViewController, la conformité est faite ici:

 class ViewController: UIViewController, getDataDelegate 

Définition de la méthode de protocole dans First View Controller (ViewController)

 func getDataFromAnotherVC(dataSsortingng : Ssortingng) { // dataSsortingng from SecondVC lblForData.text = dataSsortingng } 

Au cours de la poussée du SecondVC de First View Controller (ViewController)

 let objectPush = SecondVC() objectPush.delegateCustom = self self.navigationController.pushViewController(objectPush, animated: true) 

Première classe:

 protocol NetworkServiceDelegate: class { func didCompleteRequest(result: Ssortingng) } class NetworkService: NSObject { weak var delegate: NetworkServiceDelegate? func fetchDataFromURL(url : Ssortingng) { delegate?.didCompleteRequest(url) } } 

Seconde classe:

 class ViewController: UIViewController, NetworkServiceDelegate { let network = NetworkService() override func viewDidLoad() { super.viewDidLoad() network.delegate = self network.fetchDataFromURL("Success!") } func didCompleteRequest(result: Ssortingng) { print(result) } } 

Très facile étape par étape (100% de travail et testé)

step1: Créer une méthode sur le premier contrôleur de vue

  func updateProcessStatus(isCompleted : Bool){ if isCompleted{ self.labelStatus.text = "Process is completed" }else{ self.labelStatus.text = "Process is in progress" } } 

step2: définir un délégué tout en poussant vers le contrôleur de la seconde vue

 @IBAction func buttonAction(_ sender: Any) { let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as! secondViewController secondViewController.delegate = self self.navigationController?.pushViewController(secondViewController, animated: true) } 

step3: définir le délégué comme

classe ViewController: UIViewController, ProcessStatusDelegate {

step4: Créer un protocole

 protocol ProcessStatusDelegate:NSObjectProtocol{ func updateProcessStatus(isCompleted : Bool) } 

step5: prendre une variable

 var delegate:ProcessStatusDelegate? 

step6: Revenir à la vue précédente

 @IBAction func buttonActionBack(_ sender: Any) { delegate?.updateProcessStatus(isCompleted: true) self.navigationController?.popViewController(animated: true) } @IBAction func buttonProgress(_ sender: Any) { delegate?.updateProcessStatus(isCompleted: false) self.navigationController?.popViewController(animated: true) } 

Les delegates sont un modèle de conception qui permet à un object d’envoyer des messages à un autre object lorsqu’un événement spécifique se produit. Imaginez qu’un object A appelle un object B pour effectuer une action. Une fois l’action terminée, l’object 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 delegates! Voici un tutoriel mettant en œuvre les delegates pas à pas dans swift 3

Lien du tutoriel

Exemple simple:

 protocol Work: class { func doSomething() } class Manager { weak var delegate: Work? func passAlong() { delegate?.doSomething() } } class Employee: Work { func doSomething() { print("Working on it") } } let manager = Manager() let developer = Employee() manager.delegate = developer manager.passAlong() // PRINTS: Working on it 

Les solutions ci-dessus semblaient un peu couplées et évitaient en même temps de réutiliser le même protocole dans d’autres contrôleurs, c’est pourquoi je suis venu avec la solution plus typée en utilisant un effacement de type générique.

 @noreturn public func notImplemented(){ fatalError("not implemented yet") } public protocol DataChangedProtocol: class{ typealias DataType func onChange(t:DataType) } class AbstractDataChangedWrapper : DataChangedProtocol{ func onChange(t: DataType) { notImplemented() } } class AnyDataChangedWrapper : AbstractDataChangedWrapper{ var base: T init(_ base: T ){ self.base = base } override func onChange(t: T.DataType) { base.onChange(t) } } class AnyDataChangedProtocol : DataChangedProtocol{ var base: AbstractDataChangedWrapper init(_ s: S){ self.base = AnyDataChangedWrapper(s) } func onChange(t: DataType) { base.onChange(t) } } class Source : DataChangedProtocol { func onChange(data: Ssortingng) { print( "got new value \(data)" ) } } class Target { var delegate: AnyDataChangedProtocol? func reportChange(data:Ssortingng ){ delegate?.onChange(data) } } var source = Source() var target = Target() target.delegate = AnyDataChangedProtocol(source) target.reportChange("newValue") 

sortie : nouvelle valeur newValue

En swift 4.0

Créer un délégué sur la classe qui doit envoyer des données ou fournir des fonctionnalités à d’autres classes

Comme

 protocol GetGameStatus { var score: score { get } func getPlayerDetails() } 

Après cela dans la classe qui va confirmer à ce délégué

 class SnakesAndLadders: GetGameStatus { func getPlayerDetails() { } }