web-dev-qa-db-fra.com

Les délégués en bref?

Comment fait-on pour faire un délégué, c'est-à-dire NSUserNotificationCenterDelegate en swift?

125
user3718173

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

L'implémentation 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;
70
Adam

Voici une petite aide sur les délégués entre deux contrôleurs de vue: 

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

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

Step2: Déclarer le délégué dans la classe d'envoi (c'est-à-dire UIViewcontroller)

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

Step3: Utilisez le délégué dans une méthode de classe pour envoyer les données à la méthode de réception, qui est une 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émentez la méthode delegate

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

Étape 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.colorString = colorLabel.text
        vc.delegate = self
    }
}

Et ça devrait marcher. Ce ne sont bien sûr que des fragments de code, mais cela devrait vous donner l’idée. Pour une longue explication de ce code, vous pouvez consulter mon entrée de blog ici: 

segues et délégués

Si vous êtes intéressé par ce qui se passe sous le capot avec un délégué, j'ai écrit à ce sujet ici: 

sous le capot avec des délégués

211
MakeAppPie

Les délégués me confondaient toujours jusqu'à ce que je me rende compte que un délégué est simplement une classe qui travaille pour une autre classe. C'est comme si quelqu'un d'autre était là pour faire tout le sale boulot 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 aimez.

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 résumé, la création et l’utilisation du modèle de délégué comportent trois éléments clés.

  1. le protocole qui définit ce que le travailleur doit faire
  2. la classe boss qui a une variable déléguée, qu'elle utilise pour indiquer à la classe de travailleurs ce qu'elle doit faire
  3. la classe worker qui adopte le protocole et fait le nécessaire

Vrai vie

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

  1. Communication: une classe doit envoyer des informations à une autre classe.
  2. Personnalisation: une classe veut autoriser une autre classe à le personnaliser. 

Ce qui est bien, c’est que ces classes n’ont pas besoin de se connaître auparavant, 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é à comprendre les délégués encore mieux que le documentation .

Encore une note

Les délégués qui font référence à d'autres classes qu'ils ne possèdent pas doivent utiliser le mot clé weak pour éviter les cycles de référence importants. Voir cette réponse pour plus de détails. 

87
Suragch

J'ai eu quelques corrections à poster de @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:String)
}

Deuxièmement, votre délégué doit ê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é. Cela ressemble à une instruction conditionnelle avec respondToselector dans objC mais ici vous avez tout dans une ligne: 

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

Ci-dessus, vous avez un exemple obj-C et au-dessous, vous avez un exemple Swift de son apparence.

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

Voici un Gist je mis ensemble. Je me demandais la même chose et cela m'aidait à mieux comprendre. Ouvrez-le 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 retrieved...")
        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()
30
SeeMeCode

DÉLÉGUÉS DANS Swift 2

J'explique par l'exemple de délégué avec deux viewControllers. Dans ce cas, SecondVC Object renvoie des données au premier View Controller.

Classe avec déclaration de protocole

protocol  getDataDelegate  {
    func getDataFromAnotherVC(temp: String)
}


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 First ViewController Protocol, la conformité est faite ici:

class ViewController: UIViewController, getDataDelegate

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

func getDataFromAnotherVC(temp : String)
{
  // dataString from SecondVC
   lblForData.text = dataString
}

Pendant le transfert de SecondVC à partir du premier contrôleur de vue (ViewController)

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

Première classe:

protocol NetworkServiceDelegate: class {

    func didCompleteRequest(result: String)
}


class NetworkService: NSObject {

    weak var delegate: NetworkServiceDelegate?

    func fetchDataFromURL(url : String) {
        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: String) {
        print(result)
    }


}
4
Ekambaram E

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
3
Bobby

Pas à pas, très facile (100% fonctionnel et testé)

step1: Create 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é en mode Push to second view controller

@IBAction func buttonAction(_ sender: Any) {

    let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as! secondViewController
    secondViewController.delegate = self
    self.navigationController?.pushViewController(secondViewController, animated: true)
}

step3: set delegate like

class ViewController: UIViewController, ProcessStatusDelegate {

step4: Create protocol

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

step5: prend une variable

var delegate:ProcessStatusDelegate?

step6: Pendant le retour à la méthode de délégation d'appel du contrôleur de vue précédente, le premier contrôleur de vue doit alors notifier les données.

@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)

}
3
Mr.Javed Multani

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 que l'action est terminée, l'objet A doit savoir que B a terminé la tâche et prendre les mesures nécessaires, vous pouvez le faire avec l'aide des délégués! Voici un tutoriel pour implémenter les délégués, étape par étape dans Swift 3

Lien du tutoriel

2
James Rochabrun

Les solutions ci-dessus semblaient un peu couplées, tout en évitant de réutiliser le même protocole dans d'autres contrôleurs. C'est pourquoi je propose une solution plus typée utilisant l'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<DataType> : DataChangedProtocol{

    func onChange(t: DataType) {
        notImplemented()
    }
}


class AnyDataChangedWrapper<T: DataChangedProtocol> : AbstractDataChangedWrapper<T.DataType>{

    var base: T

    init(_ base: T ){
        self.base = base
    }

    override func onChange(t: T.DataType) {
        base.onChange(t)
    }
}


class AnyDataChangedProtocol<DataType> : DataChangedProtocol{

    var base: AbstractDataChangedWrapper<DataType>

    init<S: DataChangedProtocol where S.DataType == DataType>(_ s: S){
        self.base = AnyDataChangedWrapper(s)
    }

    func onChange(t: DataType) {
        base.onChange(t)
    }
}



class Source : DataChangedProtocol {
    func onChange(data: String) {
        print( "got new value \(data)" )
    }
}


class Target {
    var delegate: AnyDataChangedProtocol<String>?

    func reportChange(data:String ){
        delegate?.onChange(data)
    }
}


var source = Source()
var target = Target()

target.delegate = AnyDataChangedProtocol(source)
target.reportChange("newValue")    

sortie : a une nouvelle valeur newValue

0
Jans

Dans Swift 4.0

Créer un délégué sur une 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() {

 }
}
0
Saranjith