[RESOLU][Swift]Utiliser une closure @escaping pour passer un paramètre

DrakenDraken Membre
août 2017 modifié dans Dev. iOS, watchOS, tvOS #1

On peut utiliser une closure @escaping pour transmettre un événement à  un ViewController, par exemple la fin d'un traitement.


a



class MonObjet {
init(closure: @escaping ()->Void) {
// Traitements divers
// ....
closure()
}
}

a


Utilisation :


a



class ViewController: UIViewController {

var monObjet:MonObjet?

override func viewDidLoad() {
super.viewDidLoad()

monObjet = MonObjet(closure: { self.notificationFinOperation() })
}

func notificationFinOperation() {
print ("Le traitement est terminé")
// Destruction objet
monObjet = nil
}

}


a


Je me demande s'il y a un moyen de transmettre un paramètre au ViewController, de telle manière que la fonction de notification puisse s'écrire :


a



func notificationFinOperation(valeur:Int) {
print (" Valeur de retour : " , valeur)
// Destruction objet
monObjet = nil
}


a


La seule solution que j'ai trouvé pour l'instant est d'associer une variable à  la classe MonObjet.


a



class MonObjet {

var valeur = 0

init(closure: @escaping ()->Void) {
// Traitements divers
// ....
valeur = 153
closure()
}
}



a


Et de lire son contenu lors de l'appel de la closure.


a



func notificationFinOperation() {
print ("Le traitement est terminé ")
if let valeur = monObjet.valeur {
print (" Valeur de retour : " , valeur)
}
// Destruction objet
monObjet = nil
}

a


Mais je trouve que ce n'est pas propre a cause de l'optionnal. Ce serait plus lisible si la notification recevait directement la valeur en paramètre.


t



func notificationFinOperation(valeur:Int) {
}


t


Une suggestion pour y arriver ?


Réponses

  • T'es pas doué, Draken. C'est facile :



    class MonObjet {
    init(closure: @escaping (Int)->Void) {
    // Traitements divers
    // ....
    closure(23)
    }
    }



    class ViewController: UIViewController {

    var monObjet:MonObjet?

    override func viewDidLoad() {
    super.viewDidLoad()

    monObjet = MonObjet(closure: { (valeur:Int) in self.notificationCompteur(valeur) })
    }

    // Traitement notification
    func notificationCompteur(_ valeur:Int) {
    print ("Valeur : ", valeur)
    }
    }
  • Il suffisait de s'appuyer sur un exemple concret fourni par Apple, non ?


    Notamment tous ces blocks @escaping (souvent nommés completionHandler) comme dans un URLSession ?


  • Joanna CarterJoanna Carter Membre, Modérateur
    août 2017 modifié #4

    Tu sais que tu peux faire moins de code pour ça ?



    class MonObjet
    {
    init(closure: (Int) -> Void)
    {
    // Traitements divers
    // ....
    closure(23)
    }
    }


    class ViewController: UIViewController
    {
    var monObjet:MonObjet?

    override func viewDidLoad()
    {
    super.viewDidLoad()

    monObjet = MonObjet()
    {
    valeur in

    print ("Valeur : \(valeur)")
    }
    }
    }

  • DrakenDraken Membre
    août 2017 modifié #5

    L'objectif n'est pas d'afficher une valeur, mais d'envoyer des notifications à  une fonction du ViewController, via une closure. En lisant ton exemple, je présume que l'on peut l'écrire comme ça :


    a



    class ViewController: UIViewController
    {
    var monObjet:MonObjet?

    override func viewDidLoad()
    {
    super.viewDidLoad()

    monObjet = MonObjet()
    {
    valeur in
    self.notificationCompteur(valeur)
    }
    }
    }


    a


    Correct ?



  • Il suffisait de s'appuyer sur un exemple concret fourni par Apple, non ?


    Notamment tous ces blocks @escaping (souvent nommés completionHandler) comme dans un URLSession ?




    Je n'ai rien trouvé de convainquant en faisant une recherche sur internet. Et mon niveau d'anglais était .. euh .. ce qu'il est, ce n'est pas gagné. Enfin j'ai quand même fini par trouver.

  • Joanna CarterJoanna Carter Membre, Modérateur


    L'objectif n'est pas d'afficher une valeur, mais d'envoyer des notifications à  une fonction du ViewController, via une closure. En lisant ton exemple, je présume que l'on peut l'écrire comme ça :


    a



    class ViewController: UIViewController
    {
    var monObjet:MonObjet?

    override func viewDidLoad()
    {
    super.viewDidLoad()

    monObjet = MonObjet()
    {
    valeur in
    self.notificationCompteur(valeur)
    }
    }
    }


    a


    Correct ?




     


    Oui, et non  ::)


     


    Le closure est déjà  une fonction du viewController qui peut accéder n'importe quel membre de la classe.


     


    Si tu n'as pas besoin d'appeler la fonction d'ailleurs, le closure suffirait.

  • DrakenDraken Membre
    août 2017 modifié #8


    Oui, et non  ::)


     




    >:(


     




     


    Le closure est déjà  une fonction du viewController qui peut accéder n'importe quel membre de la classe.


     


    Si tu n'as pas besoin d'appeler la fonction d'ailleurs, le closure suffirait.




     


     


    Je comprend le sens des mots, pas les phrases complètes. Un petit exemple en code, SVP, sur la meilleure manière de faire pour que la fonction jeRecoisUneNotification() du ViewController reçoive une valeur d'un objet à  travers d'une closure ?


    a



    func jeRecoisUnenotification(valeur:Int) {
    // JeFaisDesTrucsIci ..
    }


  • Joanna CarterJoanna Carter Membre, Modérateur

    class ViewController: UIViewController
    {
    var monObjet:MonObjet?

    @IBOutlet weak var label: UILabel!

    override func viewDidLoad()
    {
    super.viewDidLoad()

    monObjet = MonObjet()
    {
    valeur in

    self.label.text = String(valeur)
    }
    }
    }
Connectez-vous ou Inscrivez-vous pour répondre.