Push, Pop, Push, Pop, Memory Leak
Bonjour !
J'ai un petit soucis qui me prend la tête, j'aimerai que vous me donniez votre avis.
Voilà je fais une application pour iOS et j'ai des fuites de mémoire sévère au point que le système tue mon app, elle consomme parfois jusqu'a 550mo ..
La structure est toute simple :
Une UITableView et lorsqu'on touche une cellule, on push un ViewController. Classique.
Mais si on revient a la vue de la table, qu'on sélectionne une autre cellule (ou la même), rebelote, un ViewController affiche les données.
Le problème c'est que si on fait ça 20, 30 ou 50 fois, a chaque retour a la vue principale, on ne libère pas totalement la mémoire des viewcontrollers.
Alors j'ai lu que c'est fait de manière a ce que si on choisi de revenir dessus, il garde en mémoire pour aller plus vite. Mais pour moi c'est un gros problème.
Il s'agit d'une app qui liste des annonces, l'utilisateur peut être amené a ouvrir réellement beaucoup d'annonces.
Voici le code de mon didSelectRowAtIndexPath qui push le viewcontroller.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if(cell.tag != 1) {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
Annonce_ViewController *annonce_viewController = [[Annonce_ViewController alloc] init];
annonce_viewController.annonce = [annonces objectAtIndex:indexPath.row];
[self.navigationController pushViewController:annonce_viewController animated:YES];
}
}
Je sèche. ???
Merci de votre aide.
Réponses
Regarde si tu n'as pas un strong qui gênerait la déalloc, ou un NSTimer par exemple.
Le premier réflexe à avoir, dans un tel cas, est d'utiliser Instruments > Leaks (dans le menu Product > Profile de Xcode).
Le code de ton exemple est-il complet ? En particulier, n'y a-t-il pas de délégation avec Annonce_ViewController ?
Dans mon didSelectRowAtIndexPath c'est bien le code exacte.
J'essaye depuis quelque temps d'utiliser Instruments mais c'est une usine a gaz pour moi. Cependant si j'ai bien lu ce qu'il me disait, il disait qu'un élément WebCore était retenu.
Le problème serait donc sur le viewcontroller qui est "pushé". En commentant toutes les méthodes j'ai fini par trouver ce qui cloche.
J'ai une MKMapView qui affiche la ville ou l'annonce se situe.
Quand j'enlève cette map, je n'ai plus de fuite de mémoire.
Voici le code au complet.
Oui je sais c'est particulier de se servir de "viewForFooterInSection" pour ajouter la vue MKMapView, d'ailleurs c'est peut-être de là que viens le soucis ?
En voyant que le problème venait de MKMapView j'ai mis dans un "viewWillDisappear" ceci :
Mais c'est pareil, fuite de mémoire.
Je ne vois rien d'évident dans ce code.
Pour Instruments, je suis d'accord que ce n'est pas simple, mais il y a de bons tutos:
https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/FindingLeakedMemory.html
Ce que tu cherches à savoir:
1) quel est l'objet qui est alloué à chaque push et jamais libéré ("persistent")
2) quel objet a instancié ou retenu cet objet sans le libérer
3) voir si lui-même n'est pas retenu par un objet qui ne le retient pas.
Certes, il faut comprendre un peu comment marche Instruments, mais ensuite, c'est un bug qu'on règle en 5 mn.
Te serait-il possible de garder la même mapView pour toutes tes cells ?
Et de ne changer que ses paramètres ?
En effet, en mettant par exemple le mapView dans mon Delegate, en l'appelant ensuite, juste en modifiant ses paramètre sa fonctionne.
La mapView n'est jamais libérée mais sa fonctionne. Merci beaucoup pour votre aide à tous !
Si tu as un peu de temps, ce serait encore mieux de trouver la fuite.
Si tu n'as plus de leaks avec le code que tu as montré c'est que cela vient du block.
Essaye d'enlever juste le dispatch_async qui référence mapview dans ton block.
mapView est plutôt self.mapView. Du coup, il faut le passer dans le block comme weak; sinon, tu crées une référence circulaire entre le block et self.
e.g.
Le block retient self, mais qui retient le block ?
Du nouveau ducoup. J'ai oublié de précisé un point important. Je testé mes codes sous iOS 10 et Xcode 8, avec lequel j'avais tant de leak. Avec Xcode 7 et iOS 9 tout fonctionne et je n'ai pas de fuite de mémoire, l'app ne monte plus a 500mo.