web-dev-qa-db-fra.com

Deinit n'a jamais appelé

Je crée un objet ViewController en le transmettant à un contrôleur de navigation . Lorsque l'objet est extrait de la pile, il n'est pas libéré ni Deinit n'est appelé. Quelle peut en être la raison?

Voici le code qui pousse:

self.navigationController?.pushViewController(CustomViewController(), animated: true)

Et voici le code qui apparaît:

 self.navigationController?.popViewControllerAnimated(true)
39
YogevSitton

J'ai eu le même problème. J'ai ajouté la méthode deinit vide à ma classe et ajouté un point d'arrêt: 

deinit {

}

Comme résultat, il n'est jamais appelé.
Dès que j'ai ajouté du code au corps, il a commencé à fonctionner comme prévu: 

deinit {
    print("deinit called")
}

Assurez-vous donc que votre méthode deinit n'est pas vide.
PS. J'utilise Swift 2, Xcode 7.1

53
Vlad Papko

Est-ce que certaines de vos classes ou propriétés qu'elles contiennent font référence au contrôleur de vue que vous avez sauté? 

Si votre UIViewController a créé une instance d'objet, qui à son tour crée une référence "forte" à ce contrôleur de vue (par exemple, une référence qui n'est pas explicitement déclarée "faible" ou "non possédée") et que votre contrôleur de vue conserve une référence forte à cet objet aussi, aucun ne sera désalloué. C'est ce qu'on appelle un cycle de référence fort, documenté ici (à lire absolument pour les développeurs Swift sérieux):

Le langage de programmation Swift (Swift 3.0.1): comptage automatique des références

Les fermetures sont un cas plus insidieux où vous pouvez avoir des ennuis.

Une chose que vous pouvez essayer en tant qu’expérience est d’appuyer sur le contrôleur et de le décompresser avant, vous ne faites rien dans viewDidLoad ou dans l’initialisation, et vous voyez si la méthode deinit est appelée. Si c'est le cas, vous devriez être en mesure de découvrir progressivement ce que vous faites, ce qui conduit au symptôme que vous observez.

Une autre chose qui peut déjouer le diagnostic (comme d'autres réponses l'ont souligné), que j'ai appris à la dure, est que le point d'arrêt du débogueur ne sera pas pris pour deinit () si la méthode deinit ne contient aucune instruction exécutable, car le système d'exploitation ou le compilateur optimise l’invocation deinit si elle est vide, mettez donc au moins une instruction print si vous voulez vérifier que deinit () est appelé.

38
clearlight

J'utilisais ce tutoriel Custom TabBar avec un seque personnalisé sur la page donnée. Le problème de mémoire était dû à une sous-vue qui avait une référence forte au contrôleur de vue parent.

class WBMNewsFeedV: UIView
{
   var parentVC:WBMHomeTabVC!
}

WBMNewsFeedV - sous-classe 

parentVC: WBMHomeTabVC - classe parent ViewController

Je l'ai changé pour:

class WBMNewsFeedV: UIView
{
    weak var parentVC:WBMHomeTabVC!
}

Ainsi, la référence forte était imbriquée dans une sous-vue et non visible au début. J'espère que cela aide quelqu'un. Après le changement, deinit a toujours été appelé 

WBMHomeTabVC

14
MB_iOSDeveloper

J'ai eu le même problème lorsque NotificationCenter tenait une référence forte à la vue présentée contrôlée et ainsi il n'a jamais été publié. Je devais donc ajouter [moi faible] au bloc comme ceci:

(dans le viewDidLoad)

NotificationCenter.default.addObserver(forName: .showFoo, object: nil, 
  queue: OperationQueue.main) { [weak self] (notification) in
    if let foo = notification.userInfo?["foo"] as? Foo {
            self?.afooButton!.setImage(UIImage(named: "foo"), for: .normal)
    }
}
8
David Hernandez

J'ai eu une minuterie dans mon contrôleur de vue, exécutant chaque minute pour mettre à jour une étiquette. Je mets un appel à deinit pour invalider le chronomètre, ce qui, j'en suis presque sûr, est ce que j'ai toujours fait dans Objective-C (en dealloc) et cela a fonctionné. Mais cela semble un peu différent dans Swift, j'ai donc déplacé le code de création/invalidation de temps pour afficherWillAppear/viewWillDisappear (ce qui est vraiment plus logique) et tout semble aller bien maintenant!

6
CMash

Je viens de rencontrer un problème similaire. Mon problème semble avoir été causé par une forte référence à un contrôle dont l'affectation de délégué n'est pas spécifiée comme étant "faible" avec un protocole de type classe. 

5
nwales

ajoutez un code de ligne in deinit. Si vous placez un point d'arrêt dans Empty deinit, le compilateur ne vous arrêtera pas là.

deinit {
print("any thing")
}

Ça va marcher ;)

5
Devesh

J'ai fait face au même problème. Dans mon cas, un cycle sans fin de UIView.animateWithDuration ... conserve ViewController en mémoire et bloque l'appel de deinit. Si vous utilisez quelque chose comme ceci, vous devez l’arrêter avant de supprimer ViewController. J'espère que cela pourra aider.

1
Joe

Juste pour ajouter un cas Edge que j'ai trouvé très difficile à détecter:

Si vous allouez des UnsafeMutablePointers et fournissez self (le UIViewController) comme pointeur à l'intérieur de votre contrôleur de vue, veillez à appeler pointer.deinitialize(count:), pas seulement pointer.deallocate()

Sinon, la référence à self restera et le UIViewController ne sera pas désinitialisé.

1
Teodor Iuliu Radu

Tout d’abord, assurez-vous de définir deinit

deinit {
    print("OverlayView deinit")
}

Utilisez le graphe d'objets de Xcode pour vérifier le nombre d'instances en cours de création et si elles ne sont pas désallouées, elles continueront de croître . Je créais la propriété d'un autre ViewController au-dessus du fichier. la portée, il a été utilisé qui a résolu mon problème. Et sa deinit a commencé à appeler.

De plus, j’utilisais une propriété uiview pour afficher une superposition qui devait être accessible à partir de mon contrôleur de vue à certains endroits, je la rend facultative et la définissait à zéro après avoir appelé removefromsuperview. 

var overlay: OverlayView?
overlay = nil

Si dealloc n’appelle toujours pas, un problème de cycle de conservation peut se produire, comme décrit ci-dessus. Dans ce cas, vous devrez également vérifier un autre contrôleur de vue (B) si ce dernier rappelle ce contrôleur (A) puis définit l’un d’eux comme variable faible. 

0
Ammar Mujeeb