Cycle de vie d'une vue

Bonjour à tous,
Petit soucis : J’ai une appli avec 2 vues dons la navigation est gérée par le “navigation controller”.
La première, présente un menu, et la seconde, l’affichage et l’animation en fonction du choix effectué sur la première. La navigation se passe bien, cependant, je n’arrive pas à faire en sorte que l’animation (un timer et un son qui est joué, lié au timer) s’arrête. J’ai essayé avec les fonctions viewDidAppear et meme viewWillAppear, et rien n’y fait. J’ai la garantie qu’elles sont bien appelé lors de la transition, mais quand bien meme je suis sur la premiere vue, l’animation de la seconde continue…
Si quelqu’un a une idée…
Merci à vous

Est-ce que tu détruit le timer en quittant la seconde vue ?

// KILL KILL Timer !!
timer.invalidate()
timer = nil

Si ce n’est pas le cas, il reste actif et continue sa petite vie dans la mémoire …

C’est exactement ce que je fais dans la fonction viewWillDisappear… Mais il doit y avoir un truc que je ne voie pas car il ne rentre pas dans mon if :

override func viewWillDisappear(_ animated: Bool) {

    let operationManager = OperationManager()
    
    if operationManager.minuteur != nil {
        print("minuteur existant !!!")
        operationManager.minuteur?.invalidate()
        operationManager.minuteur = nil
    }
}

Peux-tu donner l’intégralité de ton code pour voir ce qui se passe ?

Ca risque de faire beaucoup mais pour te donner une idée faut que je sois complet :
J’ai une vue pour le menu
Une pour l’appli en elle meme
Cette derniere et gérée par 2 classes : ViewController au sein de laquelle je gere tout l’aspect visuel et une autre classe au sein de laquelle est implémenté toutes mes fonction et methodes. Les deux sont liées via un protocole.
Pour ce qui est du code…
Dans la classe OperationManager :

Création du minuteur

func startMinuteur(){
if minuteur == nil{
minuteur = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.decompte), userInfo: nil, repeats: true)
compteur = 10
print (y)
}else{
minuteur!.invalidate()
minuteur = nil
startMinuteur()
}
}

Mon décompte
> @objc func decompte(){

    if let del = delegate{
        // on envoi au viewcontroller la valeur du compteur pour qu'elle s'affiche a l'ecran
        del.updateDisplay(value: compteur)
    }
    
    if compteur == 0{
        if let del = delegate{
            del.timeOut()
            stopMinuteur()
        }
    }
    compteur -= 1
}

Dans ma classe ViewController
> override func viewWillDisappear(_ animated: Bool) {

    let operationManager = OperationManager()
    operationManager.minuteur?.invalidate()
    operationManager.minuteur = nil
    
}

Si il te faut plus, je t’enverrais des copies écrans

Merci

Je ne suis pas sûr d’avoir compris l’enchainement souhaité, mais je dirais qu’il est sans doute logique que ton minuteur retourne nil juste après avoir instancié OperationManager.
-> du coup, normal également qu’il ne rentre pas dans ton if.

Es-tu certain de devoir passer par un protocol pour implémenter le résultat attendu ?

Salut lolabj
Si mon minuteur retourne “nil”, comment expliquer qu’il continue de tourner ?
Pour le Protocol, cela résulte de ma collaboration avec un autre xcodeur, mais je ne pense pas que cela soit génant… A moins que ce le soit…

Non pas forcément génant, mais peut-être plus compliqué à manipuler ?

Si le minuteur continue de tourner, c’est peut-être le minuteur d’une autre instance de OperationManager ?

Apparemment, il commence à tourner à l’invocation de la méthode startMinuteur par laquelle tu charges la propriété minuteur de la classe OperationManager.

Ici :

override func viewWillDisappear(_ animated: Bool) {

    let operationManager = OperationManager()

    if operationManager.minuteur != nil {
        print("minuteur existant !!!")
        operationManager.minuteur?.invalidate()
        operationManager.minuteur = nil
    }
}
  • tu instancies operationManager comme un objet de type OperationManager
  • tu n’appelles pas la méthode operationManager.startMinuteur
  • et tu voudrais que operationManager.minuteur ne soit pas nil ?
1 « J'aime »

Oh punaise lolo je t’aime… En effet j’avais 2 instances de ma classe OperationManager… C’était ça !!!
Mon minuteur s’arrête bien du coup quand je reviens sur ma vue précédente.
Mille mercis :slight_smile:

Bien content pour toi :wink:

1 « J'aime »

J’en profite pour donner un petit conseil. Plutôt qu’un appel récursif, pas toujours lisible et difficilement debuggable : [quote=“BillyZeBlack, post:5, topic:517”]
func startMinuteur(){
if minuteur == nil{
minuteur = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.decompte), userInfo: nil, repeats: true)
compteur = 10
print (y)
}else{
minuteur!.invalidate()
minuteur = nil
startMinuteur()
}
}
[/quote]
Tu pourrais faire ceci :

func startMinuteur(){
    if let minuteur = minuteur {
        minuteur.invalidate()
    }

    minuteur = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.decompte), userInfo: nil, repeats: true)
    compteur = 10
    print (y)
}
1 « J'aime »

@mbritto Je ne sais pas pourquoi, mais ta version a l’air effectivement bien plus clair et aérée…
Merci pour le conseil… Que je vais suivre

1 « J'aime »

Avec plaisir! Les appels récursifs sont souvent plus difficiles à lire (hors parcours d’arbres ou de listes chaînées) et moins performants.