Ok, voici l'affaire, je déteste poser des questions sur mon débogage et mes plantages. Parce que je les gère généralement moi-même, mais je ne peux tout simplement pas contourner cela, même après avoir déjà vu plusieurs questions .
Ok, voici le problème, je trouve mon application allumée et désactivée au hasard avec cette trace de pile:
*** -[ViewController respondsToSelector:]: message sent to deallocated instance 0x1e5d2ef0
Où ViewController
peut varier, parfois l'endroit où mon code se bloque, n'a AUCUNE pertinence pour ce particulier ViewController
et ne le possède pas ou ne l'appelle pas.
De plus, pour obtenir cette trace de la console, j'ai activé Zombies, sinon je n'aurais aucune impression de console, je n'obtiendrais que:, objc_msgSend
ce que je sais signifie que je envoie un message qui est publié. Mais je ne trouve pas où c'est ... je suis vraiment coincé! Habituellement, je débogue toujours mes plantages, donc je suis vraiment coincé là-dessus.
Encore une fois, cela se bloque à différents endroits à des moments différents, par intermittence. Et l'endroit où il se bloque n'a presque aucun rapport avec le ViewController
. Et je trouve cela très déroutant.
Avez-vous besoin de mon code? J'ai beaucoup de fichiers et comme il plante à différents endroits, distribuer mon code sera un gâchis!
J'ai essayé d'ajouter des points d'arrêt symboliques sans succès, et Zombies n'est pas disponible sur l'application Instruments pour iOS. Je ne peux pas exécuter mon application sur le simulateur car elle a des cadres d'architecture non compatibles.
Merci tout le monde...
la source
Réponses:
Utilisez Instruments pour rechercher les erreurs d'instance désallouées. Profil de votre application ( Cmd ⌘+ I) et choisissez le modèle Zombies . Une fois votre application en cours d'exécution, essayez de la planter. Vous devriez obtenir quelque chose comme ça:
Cliquez sur la flèche à côté de l'adresse dans le popover pour afficher l'objet qui a été appelé après avoir été désalloué.
Vous devriez voir maintenant chaque appel qui a changé le nombre de rétention de cet objet. Cela peut être dû à l'envoi direct de messages de conservation / libération ainsi qu'à la vidange des pools de libération automatique ou à l'insertion dans des NSArrays.
La colonne RefCt affiche retientCount après que l'action a été appelée et l'appelant responsable affiche le nom de la classe et la méthode dans laquelle elle a été effectuée. Lorsque vous double-cliquez sur une conservation / libération, les instruments vous montreront la ligne de code où cela a été effectué (si cela ne fonctionne pas, vous pouvez examiner l'appel en le sélectionnant et en choisissant son homologue dans le volet Détails étendus ):
Cela vous permettra d'examiner tout le cycle de vie de l'objet retentionCount et vous trouverez probablement votre problème tout de suite. Tout ce que vous avez à faire est de trouver manquant de retenir pour le dernier communiqué .
la source
release
, en particulier. Le problème est tout déséquilibrérelease
. Je peux aussi simplement être un échec àretain
quelque chose sur lequel vous gardez un pointeur et auquel vous faites référence plus tard.eu un problème similaire. Dans mon cas, un viewController devait obtenir les événements navigationController, il s'enregistrait donc en tant que délégué du contrôleur de navigation:
Le crash se produit lorsque ce contrôleur a été désalloué mais était toujours le délégué du contrôleur de vue. L'ajout de ce code dans dealloc n'a eu aucun effet:
car au moment où dealloc est appelé, le contrôleur de vue a déjà été supprimé de la hiérarchie de vue, donc self.navigationController est nul, donc la comparaison échouera à coup sûr! :-(
La solution consistait à ajouter ce code pour détecter le VC quittant la hiérarchie de vue juste avant qu'il ne le fasse réellement. Il utilise une méthode introduite dans iOS 5 pour déterminer quand la vue est affichée et non poussée
Plus de plantages!
la source
Pour tous ceux qui ne peuvent pas le résoudre, voici quelques autres techniques:
https://stackoverflow.com/a/12264647/539149
https://stackoverflow.com/a/5698635/539149
https://stackoverflow.com/a/9359792/539149
https://stackoverflow.com/a/15270549/539149
https://stackoverflow.com/a/12098735/539149
Vous pouvez exécuter des instruments dans Xcode 5 en cliquant sur la fenêtre contextuelle du projet-> Modifier le schéma ... Profil -> Instrument et choisissez Allocations ou Fuites, puis profilez votre application, puis arrêtez les instruments, cliquez sur le bouton info dans Allocations et "Activer la détection NSZombie" .
Cependant, pour les messages provenant directement du fil de discussion com.apple.main, cela ne révélera probablement rien.
Je me suis cogné la tête là-dessus pendant plus de deux heures et la réponse s'est avérée être une sur-version, que j'ai découverte en commentant une copie de mon projet par la force brute jusqu'à ce que je trouve le coupable:
Le problème est que release ne définit pas la variable sur NULL.
Cela signifie que le définir sur NULL appelle à nouveau la libération, décrémentant le refcount et libérant la mémoire immédiatement jusqu'à plus tard, lorsque les variables qui font référence à viewController en ont fini avec lui.
Activez donc ARC ou assurez-vous que votre projet utilise de manière cohérente release ou NULL, mais pas les deux. Ma préférence est d'utiliser NULL car il n'y a alors aucune chance de référencer un zombie mais cela rend plus difficile de trouver où les objets sont libérés.
la source
J'avais rencontré le même problème dans iOS hier. J'ai créé IAP dans la sous-vue App "About", et j'ai ajouté Transaction Observer dans "About" viewDidLoad. Lorsque j'achète pour la première fois, aucun problème, mais après être revenu à la fenêtre principale et entré à propos de la sous-vue pour acheter à nouveau, le problème "message envoyé à l'instance désallouée" s'est produit et l'application s'est plantée.
Après avoir supprimé Transaction Observer dans dealloc, le problème est résolu.
la source
zombie
J'obtenais un objet pour les achats inApp. Après de nombreuses heures à creuser, j'ai trouvé celui-ci ... UN GRAND MERCI Homme.J'ai eu un problème très similaire et j'ai compris que c'était dû au jeu de délégués du contrôleur de navigation.
Le ci-dessous a résolu mon problème,
la source
Eu le même problème dans OS X.
Pour résoudre cette
- (void)dealloc
méthode pas assez comme @SoftwareEvolved l'a déjà dit. Mais malheureusement,- (void)viewWillDisappear
n'est disponible que sur la version 10.10 et ultérieure.J'ai introduit une méthode personnalisée dans ma sous-classe NSViewController où définir toutes les références zombie-dangereuses à nil. Dans mon cas, c'était des
NSTableView
propriétés (delegate
etdataSource
).C'est tout. Chaque fois que je suis sur le point de supprimer la vue de la supervision, appelez cette méthode.
la source
J'ai eu le même problème.Il était difficile de trouver quel délégué causait un problème, car il n'indique aucune ligne ou instruction de code.J'ai donc essayé un moyen, peut-être que cela vous sera utile.
la source