Délégués à swift?

Comment faire un délégué, i.e. NSUserNotificationCenterDelegate dans swift?

120
demandé sur Benjamin 2014-06-07 20:23:58

12 réponses

Il n'est pas différent de l'obj-c. Tout d'abord, vous devez spécifier le protocole dans la 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;
69
répondu Adam 2016-03-15 04:33:28

Voici un peu d'aide sur les délégués entre deux contrôleurs de vue:

Étape 1: faites un protocole dans le UIViewController que vous allez supprimer/que vous allez envoyer les données.

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

etape n ° 2: Déclare le délégué de l'envoi de la classe (c'est à dire UIViewcontroller)

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

Etape 3: Utiliser le délégué dans une méthode de classe pour envoyer les données pour 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: adopter le protocole dans la classe de réception

class ViewController: UIViewController, FooTwoViewControllerDelegate {

Étape 5: mettre en Œuvre la méthode du délégué

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

Étape 6: Définir le délégué de l'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. C'est de entendu seulement des fragments de code, mais devrait vous donner l'idée. Pour une longue explication de ce code, vous pouvez aller à mon article de blog ici:

séquences 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 là-dessus:

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

207
répondu MakeAppPie 2018-02-05 11:24:47

les délégués m'ont toujours déconcerté jusqu'à ce que je réalise que un délégué est juste une classe qui fait du travail pour une autre classe . C'est comme avoir quelqu'un là pour faire tout le sale boulot pour vous que vous ne voulez pas le faire vous-même.

j'ai écrit une petite histoire pour illustrer cela. Lis-le dans une cour de récréation si tu veux.

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 à faire et utiliser le modèle de délégué.

  1. le protocole qui définit ce que le travailleur doit faire
  2. le chef de classe qui dispose d'un délégué variable, qui l'utilise pour dire le travailleur classe quoi faire
  3. la classe ouvrière qui adopte le protocole et fait ce qui est requis
"151980920 la" Vraie vie

par rapport à notre histoire de Grand Frère autoritaire 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 permettre à une autre classe de la personnaliser.

la grande partie est que ces classes n'ont pas besoin de savoir quoi que ce soit les uns des autres à l'avance, sauf que la classe déléguée est conforme au protocole requis.

je recommande vivement la lecture des deux articles suivants. Ils m'ont aidé à comprendre délégués encore mieux que le documentation fait.

une autre note

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

84
répondu Suragch 2017-05-23 12:34:40

j'ai eu quelques corrections de post de @MakeAppPie

tout d'abord quand vous créez le protocole de délégué, il 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 le cycle de conservation.

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

enfin, vous êtes en sécurité parce que votre protocole est une valeur optionnelle. Cela signifie que son message "néant" ne sera pas envoyé à ce bien. C'est similaire à conditionnel déclaration 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 ci-dessous vous avez un exemple rapide de comment il regarde.

delegate?.myMethod(self, text:"your Text")
45
répondu Shial 2016-12-02 15:22:27

voici un gist j'ai mis ensemble. Je me demandais la même chose et cela a aidé à améliorer ma compréhension. Ouvrez ceci 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
répondu SeeMeCode 2016-12-02 15:25:00

DÉLÉGUÉS À SWIFT 2

j'explique Avec exemple de délégué avec deux viewControllers.Dans ce cas, L'objet SecondVC renvoie des données au contrôleur de première vue.

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 le Premier ViewController Protocole conforme est fait ici:

class ViewController: UIViewController, getDataDelegate

définition de la méthode du Protocole dans la première vue Controller (ViewController)

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

pendant la poussée de la Seconde vc du contrôleur de première vue (ViewController)

let objectPush = SecondVC()
objectPush.delegateCustom = self
self.navigationController.pushViewController(objectPush, animated: true)
8
répondu Maninderjit Singh 2016-05-13 07:14:53

première classe:

protocol NetworkServiceDelegate: class {

    func didCompleteRequest(result: String)
}


class NetworkService: NSObject {

    weak var delegate: NetworkServiceDelegate?

    func fetchDataFromURL(url : String) {
        delegate?.didCompleteRequest(url)
    }
}

deuxième 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
répondu Ekambaram E 2017-04-18 07:43:01

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

etape n ° 1: méthode de création à première vue-contrôleur

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

etape n ° 2: Jeu de déléguer tout pousser à seconde vue-contrôleur

@IBAction func buttonAction(_ sender: Any) {

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

etape 3: set délégué comme

class ViewController: UIViewController, ProcessStatusDelegate {

etape 4: Créer protocole

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

etape n ° 5: prendre une variable

var delegate:ProcessStatusDelegate?

step6: pendant que retourner à la méthode de délégué de contrôleur de vue précédente ainsi premier contrôleur de vue notifier avec des 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)

}
4
répondu Mr.Javed Multani 2018-03-08 09:41:04

les délégués sont un motif qui permet à un objet d'envoyer des messages à un autre objet lorsqu'un événement spécifique se produit. Imaginez qu'un objet a appelle un objet B pour effectuer une action. Une fois l'action terminée, l'objet doit 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! Voici un tutoriel mettant en œuvre les délégués étape par étape dans swift 3

Tutoriel Lien

2
répondu James Rochabrun 2017-10-31 16:22:34

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
1
répondu Bobby 2017-07-08 17:35:26

les solutions ci-dessus semblaient un peu couplées et en même temps éviter de réutiliser le même protocole dans d'autres controllers, c'est pourquoi je suis venu avec la solution qui est plus forte typée en utilisant le type générique-erasure.

@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 obtenu la nouvelle valeur newValue

0
répondu Jans 2016-01-28 19:04:38

dans 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 celui de la classe qui va confirmer à ce délégué

class SnakesAndLadders: GetGameStatus {
    func getPlayerDetails() {

 }
}
0
répondu Saranjith 2017-07-27 04:22:29