2016-10-27 3 views
0

Je fais face à un problème de désallocation et peut-être à un référencement fort ou circulaire qui ne peut pas être compris. J'ai trois UIView de l'instanciation comme ci-dessous:Références fortes et problèmes de mémoire UIView

Il y a une principale ViewController que j'ai ajouté un UIView intérieur en story-board et le UIView a une sortie weak intérieur de la classe comme:

class ViewController : UIViewController { 

    //MARK: - outlets 
    @IBOutlet weak var firstView: FirstUiview! 

} 

seconde UIView est ajouté en tant que sous-vue à la première vue comme programme:

class FirstUiview : UIView { 

     //creating an instance of secondUiView 
     lazy var mySecondView: SecondViewClass = { 
      let dv = SecondViewClass() 
      dv.backgroundColor = UIColor.red 
      return dv 
     }() 


     //sometime later by clicking on a button 
     self.addSubview(mySecondView) 

     //a button will be tapped to remove mySecondView; 
     //later will be called at some point upon tapping: 

     func removingSecondViewByTapping() { 
     if mySecondView.isDescendant(of: self) { 
      mySecondView.removeFromSuperview() 
     } 
     } 

} 

maintenant, le SecondViewClass est:

class SecondViewClass : UIView { 

     //in this class I create bunch of uiview objects like below: 
     lazy var aView : UIView = { 
     let hl = UIView() 
     hl.tag = 0 
     hl.backgroundColor = UIColor.lightGray 
     return hl 
     }() 

     self.addSubview(aView) //... this goes on and I add other similar views the same way. 

     //creating an instance of thirdView 
     var let thirdView = UIView() 
     self.addSubview(thirdView) 

} 

Maintenant, si l'utilisateur appuie sur le bouton pour supprimer mySecondView puis l'ajouter à nouveau à un autre moment (toujours dans le même ViewController) J'attends tous les sous-vues de mySecondView auraient été libérés et ont disparu, mais ils sont tous là. J'apprécierais beaucoup si quelqu'un peut me le signaler où est-ce que je garde une référence forte ou s'il y a un problème de référence circulaire? ou peut-être autre chose?

+0

Pourquoi voudriez-vous attendre à des sous-vues de la 2ème vue à être parti? Supprimer mySecondView de sa vue d'ensemble ne lui fait pas supprimer toutes ses sous-vues. – dan

+0

@dan Oh, attendez, je pensais que view.removeFromSuperview va libérer et détruire la vue, y compris ses sous-vues à moins que ses sous-vues aient des références à quelque chose qui est tenu, n'est-ce pas? si non, ne pourriez-vous pas me guider sur la façon dont je peux totalement supprimer la vue d'envoi, y compris ses sous-vues? – TheeBen

Répondre

4

Vous avez deux références importantes à vos vues, votre propriété personnalisée et la référence de hiérarchie de vue établie lorsque vous appelez addSubview. Lorsque vous supprimez la vue de la hiérarchie de vue, votre classe, elle-même, a toujours sa référence forte.

Vous pouvez résoudre ce problème en rendant votre référence facultative, et lorsque vous appelez le removeFromSuperview, définissez également manuellement votre référence à nil. Ou, peut-être plus facilement, vous pouvez résoudre ce problème en utilisant les références weak, ce qui permet à la hiérarchie de vue de conserver les références solides pour vous. Et parce que votre propriété personnalisée est weak, lorsque vous le retirez de la hiérarchie de la vue (éliminant ainsi la seule référence forte à elle), votre référence weak deviendra automatiquement nil:

class FirstView: UIView { 

    weak var secondView: SecondView?  // note the `weak` reference, which is obviously an optional 

    //sometime later by clicking on a button 

    func doSomething() { 
     let subview = SecondView() 
     subview.backgroundColor = .red 
     self.addSubview(subview) 
     secondView = subview 
    } 

    // a button will be tapped to remove secondView; 
    // later will be called at some point upon tapping ... 

    func removingSecondViewByTapping() { 
     secondView?.removeFromSuperview() 
    } 
} 
+0

Merci pour votre réponse. Cela ressemble à la bonne explication et à la bonne réponse. J'ai peur que la question soit plus profonde que cela pour moi alors que j'ai essayé de la simplifier ici. Réponse très claire cependant! J'ai essayé cela sans verrou pour le moment. Ma troisième vue a un protocole que la vue parent se conforme à elle, pourrait-il être un autre problème? Je me suis assuré que c'est un délégué de protocole faible, c'est-à-dire, quelque chose comme http://stackoverflow.com/a/24104371/5601401 – TheeBen

+0

Oui, l'échec d'utiliser des protocoles faibles pourrait également être un problème. Donc, si vous avez corrigé ce qui précède et que vous vous êtes assuré d'utiliser des références de délégué 'weak', et que vous ne voyez toujours pas vos vues désallouées, vous devez diagnostiquer ce qui garde la référence forte. L'utilisation du "Graphique de la mémoire de débogage" (voir http://stackoverflow.com/a/30993476/1271826) peut être utile pour détecter d'éventuels problèmes supplémentaires. – Rob