Framework Combine ne fonctionne pas (cours ios 13, chapitre 1.7)

Bonjour,
Dans le cours de Maxime sur IOS 13, dans le chapitre 1.7 sur le Framework Combine, utiliser un subscriber sink je n’arrive pas à avoir un code qui fonctionne.

J’avais recopié exactement le même code que Maxime et ça ne fonctionen pas, du coup j’ai tenté le coup avec un code encore plus simple.

Une simple vue avec un bouton.
Un clic sur le bouton appelle la fonction « clic ».

A chaque fois que je clique sur le bouton je devrais voir s’afficher dans la console de debug :

valeur : 1

puis au clic suivant : valeur : 2 et ainsi de suite.

Hors j’ai juste valeur : 0 qui s’affiche et ensuite juste nombre : 1, nombre : 2, nombre 3, …

Je n’arrive pas à capter ce que j’ai oublié pour que ça fonctionne.

A noter que le combine_demo de Maxime ne fonctionne pas non plus.

J’ai xcode 11.4.1 sous Catalina (11.5.2)

Le code :


import UIKit
import Combine

class ViewController: UIViewController {

@Published var nombre:Int=0

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    
    $nombre.sink { (valeur) in
        print("valeur : \(valeur)")
    }
}

@IBAction func clic(_ sender: Any) {
    nombre += 1
    print("nombre : \(nombre)")
}

}

Essaie-voir de remplacer valeur par $0, pour voir. Comme dans l’exemple d’Apple : " ```
let sub = NotificationCenter.default
.publisher(for: NSControl.textDidChangeNotification, object: filterField)
.sink(receiveCompletion: { print ($0) },
receiveValue: { print ($0) })

J'ai regardé la vidéo en anglo-saxon sur le WWDC 2019, mais je dois dire que je n'ai compris que très superficiellement. Tous ces protocoles font toujours l'objet d'explications théoriques et abstraites mais ne sont utilisables vraiment que si l'on maîtrise les processus de bas niveau mis en œuvre pour les exécuter...

J’ai fait un petit programme équivalant au tien, même constat …

MAXIME … HELP !!
Autre syntaxe : @mbritto HELP !!

Effectivement il est possible qu’Apple ait changé la syntaxe entre le moment où j’ai enregistré (juillet 2019) et aujourd’hui.
Je n’ai pas réutilisé Combine depuis donc je ne m’en suis pas rendu compte mais je regarderai si je peux voir ce qui a été modifié de leur côté car c’est sûr que ça fonctionnait en Juillet.

Merci pour les réponses.

J’ai avancé un poil mais ce soir je suis trop raide pour réfléchir un peu plus.

Le code ci-dessous fonctionne dans le playground :
Ça serait une histoire en lien avec l’endroit ou j’appelle le sink ?
Une fois le viewDidLoad terminé l’enregistrement serait supprimé ?
Tel quel ça fonctionne, par contre si je supprime les 3 lignes en dessous de : let n1 = test() et que je les remplace par n1.start() ça ne fonctionne plus.

import UIKit
import Combine

class test {

@Published var nombre:Int=5

func start() {
    self.$nombre.sink { (valeur) in
        print("valeur : \(valeur)")
    }
}

func incremente() {
    nombre += 1
     print("nombre : \(nombre)")
}

}

let n1 = test()

n1.$nombre.sink { (valeur) in
print(« valeur : (valeur) »)
}

n1.incremente()
n1.incremente()
n1.incremente()

J’ai plus trop la tête à bien formuler les choses ce soir, mais problème résolu.

Explication sur stackoverflow :

Mon code qui fonctionne enfin :

class ViewController: UIViewController {

@IBOutlet weak var ui_label: UILabel!
@Published var nombre:Int=1

// Ajout ici
var ticket: AnyCancellable?
    
override func viewDidLoad() {
    super.viewDidLoad()
    
    // et on garde la référence ici
    ticket = $nombre.sink { (valeur) in
        print("valeur : \(valeur)")
    }
    
}

@IBAction func clic(_ sender: Any) {
    self.nombre += 1
    print("nombre : \(nombre)")
}   

}

2 « J'aime »

D’accord, il faut garder un lien sur le sink. Bon à savoir. Et effectivement, mon petit programme de test fonctionne avec cette syntaxe.