Fuite de mémoire (memory leak) quand transition programmée entre écrans

Bonjour,

Dans le Chapitre 4.3 (IOS Niveau avancé) Maxime explique comment passer d’un écran à l’autre sans storyboard. Cela fonctionne bien sauf que clairement la mémoire allouée au ViewController de départ (celui qui initie la transition) reste allouée.

Le scénario est le suivant :

On quitte la vue ARSCNView (c’est une vue AR mais je ne pense pas que cela change qqchose au principe) pour arriver sur l’écran de la victoire (You Rock Baby) comme ceci :

if let successScreen = self.storyboard?.instantiateViewController(identifier: "SuccessScreenView") 
{
 successScreen.modalPresentationStyle = .fullScreen
 self.present(successScreen, animated: true, completion: nil) }

Cet écran donne la possibilité de rejouer en touchant le bouton « Play again » ce qui appelle un autre écran qui à la fin rappelle le ARViewController (l’écran bleu clair à gauche sur mon snapshot) d’où on vient à l’origine comme ceci :

  if let mainGameScreen = self.storyboard?.instantiateViewController(identifier: "ARViewController")
        {
            
            mainGameScreen.modalPresentationStyle = .fullScreen
            self.present(mainGameScreen, animated: false, completion: nil)
        }

Tout cela fonctionne impeccablement … sauf que à chaque nouvelle affichage de la vue ARSCNview j’utilise 100 Meg en plus !

Le problème se présente en fait peut-être avec toutes mes transitions mais est très visible en perdant 100 Meg a chaque création de la vue AR …

Help :sweat_smile:

Merci !!

MARC

PS : Xcode 11.3 ; IOS 13.5

Salut Marc,

en effet, lorsque tu navigues vers un nouvel écran ou que tu en présente un de façon modale, l’écran précédent est conservé autant que possible par iOS, pour te permettre de revenir en arrière si besoin.
S’il vient à manquer de mémoire, il va petit à petit supprimer tout seul les anciens écrans et libérer les ressources associées.
J’ai l’impression que ton soucis est que tu ne reviens pas en arrière mais tu crées un nouvel écran de jeu à chaque fois, que tu affiches par dessus les autres. Je me trompe ?
Si tu crées un nouvel écran du même type, il va vraiment le recréer et non recycler l’ancien écran.
Il vaudrait mieux faire disparaître l’écran de la victoire pour revenir à l’écran de jeu.

Bonjour Maxime,

Merci pour la réponse super rapide !

Correct, je ne reviens pas en arrière je crée du nouveau.

La transition est en fait sur plusieurs écrans donc revenir en arrière je vois pas trop …

Ecran Principal AR → Ecran de la victoire → Ecran "Etes-vous prêts ? " → Ecran Principal AR … → Ecran de l’échec (si on rate :slight_smile: ) → Ecran « Etes vous prêts » → Ecran Principal AR, etc …

Pour revenir en arrière, faut que je revoie toute la logique (mais je peux si il n’y a pas de manière raisonnablement simple de nettoyer un écran précédent …)

Couvres-tu cela dans une leçon ?

D’un autre coté, revenir en arrière cela veut dire que le fil du code va reprendre où ? dans « viewDidLoad() » ? Et tout ce qui ce se passe dans ma Class ViewController (de l’écran précédent) n’est pas refait mais conservé d’avant alors je présume ?

Merci !!!

Marc

En effet il faudrait que tu fonctionnes comme ça si tu veux éviter de consommer de la mémoire inutilement en recréant les écrans. Tu peux le faire à la main ou alors utiliser les unwind Storyboard Segue que j’ai dû mentionner dans le cours iOS 12 (mais je ne me rappelle plus à quel chapitre).

Si tu fais un retour, il ne repasse normalement pas dans le viewDidLoad si la vue n’avait pas été supprimée, par contre il ne repassera dans le viewWillAppear. Justement tu auras des transitions beaucoup plus rapides et efficace plutôt que de tout recréer à chaque fois.

En effet ! Leçon 6.13 IOS 12. J’étais passé au dessus … Cela fonctionne donc, je reviens à la vue ARSCNView précédente par un UnwindSegue et plus de memoryLeak donc. Merci !!

MARC

1 « J'aime »