À quoi sert la -(void)viewDidUnload
?
Pourrais-je pas simplement tout relâcher dans -dealloc
? Si la vue se déchargeait, -dealloc
être appelé quand même?
En plus de ce qui a déjà été indiqué, je voulais approfondir la logique derrière -viewDidUnload
.
L'une des raisons les plus importantes de sa mise en œuvre est que les sous-classes UIViewController
contiennent généralement également des références propriétaires à diverses sous-vues dans la hiérarchie des vues. Ces propriétés auraient pu être définies via IBOutlets
lors du chargement à partir d'une nib, ou par programmation dans -loadView
, par exemple.
La propriété supplémentaire des sous-vues par le UIViewController
signifie que même lorsque sa vue est supprimée de la hiérarchie des vues et libérée pour économiser de la mémoire, à travers laquelle les sous-vues sont également libérées par la vue, elles ne seront pas réellement désallouées car le UIViewController
lui-même contient également ses propres références de conservation en suspens à ces objets. La libération du UIViewController
propriété supplémentaire de ces objets garantit qu'ils seront également désalloués pour libérer de la mémoire.
Les objets que vous libérez ici sont généralement recréés et redéfinis lorsque la vue UIViewController
est re-loaded
, à partir d'une Nib ou via une implémentation de -loadView
.
Notez également que la propriété UIViewController
view
est nil
au moment où cette méthode est appelée.
Comme le la documentation dit :
Il est appelé dans des conditions de faible mémoire lorsque le contrôleur de vue doit libérer sa vue et tous les objets associés à cette vue pour libérer de la mémoire.
Dans la même situation, dealloc
n'est pas appelé . Cette méthode est uniquement disponible dans OS3 et supérieur. Faire face à la même situation dans l'iPhone OS 2.x était une vraie douleur!
Mise à jour de juillet 2015 : il convient de noter que viewDidUnload
était déconseillé dans iOS 6 car "les vues ne sont plus purgées dans des conditions de faible mémoire et donc cette méthode n'est jamais appelée. " Donc, le conseil moderne est de ne pas s'en inquiéter et d'utiliser dealloc
.
En effet, vous définissez généralement le @property
Comme "(nonatomic, retain)"
et en tant que tel, le setter qui est créé pour vous libère l'objet actuel et conserve ensuite l'argument, c'est-à-dire.
self.property = nil;
... fait quelque chose comme:
[property release];
property = [nil retain];
Par conséquent, vous tuez deux oiseaux avec une pierre: gestion de la mémoire (libération de l'objet existant) et affectation du pointeur à zéro (car l'envoi de tout message à un pointeur nul renvoie zéro).
J'espère que cela pourra aider.
N'oubliez pas que viewDidUnload
est une méthode dans le contrôleur de vue, pas dans la vue. La méthode view'sdealloc
sera appelée lors du déchargement de la vue, mais la méthode view controllererdealloc
ne pourra être appelée que plus tard.
Si vous recevez un avertissement de mémoire insuffisante et que votre vue ne s'affiche pas, ce qui se produira par exemple à chaque fois que vous utilisez un UIImagePickerController pour permettre à l'utilisateur de prendre une photo, votre vue sera déchargée et devra être rechargée après cela.
Apple obsolète viewWillUnload, maintenant vous devez utiliser didReceiveMemoryWarning ou dealloc pour libérer vos objets.
Dans iOS 6, les méthodes viewWillUnload et viewDidUnload de UIViewController sont désormais obsolètes. Si vous utilisiez ces méthodes pour libérer des données, utilisez plutôt la méthode didReceiveMemoryWarning. Vous pouvez également utiliser cette méthode pour libérer des références à la vue du contrôleur de vue si elle n'est pas utilisée. Vous devez tester que la vue n'est pas dans une fenêtre avant de le faire.
Conclusion:
Les contrôleurs de vue ont une propriété de vue. En général, une pointe ou un morceau de code ajoute d'autres vues à cette vue. Cela se produit souvent dans une méthode -viewDidLoad, comme ceci:
- (void)viewDidLoad {
[super viewDidLoad];
[self createManyViewsAndAddThemToSelfDotView];
}
en outre, un fichier nib peut créer un bouton et l'ajouter à la vue du contrôleur de vue.
Sur iPhone OS 2.2, lorsque -didReceiveMemoryWarning a été invoqué depuis le système, vous avez dû libérer quelque chose pour libérer de la mémoire. Vous pouvez libérer la vue entière du contrôleur de vue si cela a du sens. Ou simplement de gros contenus gourmands en mémoire.
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
Maintenant, dans le nouveau système d'exploitation 3.0, il existe une méthode -viewDidUnload, qui sera invoquée depuis le système lorsque la vue a été déchargée en raison d'une mémoire insuffisante (veuillez me corriger: quand exactement cela est-il appelé?)
-viewDidUnload est utilisé pour libérer tous les objets qui appartenaient à la fois au contrôleur de vue lui-même et à la vue. La raison: si un contrôleur de vue contient des références aux enfants de la vue, c'est-à-dire un bouton, les vues enfant référencées ne seront pas libérées, car leur nombre de rétentions est> = 1. Une fois libérées dans -viewDidUnload, elles peuvent être libérées de mémoire.
Si le contrôleur de vue est extrait de la pile du contrôleur de navigation et n'est conservé nulle part ailleurs, il sera désalloué et dealloc sera appelé à la place de viewDidUnload. Vous devez libérer les vues créées dans loadView dans dealloc, mais il n'est pas nécessaire de définir les variables sur nil, car peu de temps après l'appel de dealloc, les variables n'existeront plus.
Vous pouvez libérer toutes les sous-vues auxquelles vous vous accrochez, par exemple cette UIImageView que vous avez conservée dans votre méthode loadView, ou mieux encore l'image qui était sur cette UIImageView.