Pour des raisons de clarté et de cohérence, il est recommandé de déclarer des propriétés pour tous vos IBOutlets. Les détails sont expliqués dans la section Guide de programmation de la gestion de la mémoire . L'essentiel est que, lorsque vos objets NIB ne sont pas archivés, le code de chargement de la NIB passe en revue et définit tous les IBOutlets en utilisant setValue:forKey :. Lorsque vous déclarez le comportement de gestion de la mémoire sur la propriété, il n'y a aucun mystère quant à ce qui se passe. Si la vue est déchargée, mais que vous avez utilisé une propriété déclarée comme étant conservée, vous disposez toujours d'une référence valide à votre champ de texte.
Un exemple plus concret serait peut-être utile pour indiquer pourquoi vous devriez utiliser une propriété de retenue :
Je vais faire quelques hypothèses sur le contexte dans lequel vous travaillez - je vais supposer que le UITextField ci-dessus est une sous-vue d'une autre vue qui est contrôlée par un UIViewController. Je vais supposer qu'à un moment donné, la vue est hors de l'écran (peut-être est-elle utilisée dans le contexte d'un UINavigationController), et qu'à un moment donné votre application reçoit un avertissement de mémoire.
Supposons que votre sous-classe UIViewController doive accéder à sa vue pour l'afficher à l'écran. À ce stade, le fichier nib sera chargé et les propriétés de chaque IBOutlet seront définies par le code de chargement de la nib à l'aide de setValue:forKey :. Les propriétés importantes à noter ici sont la vue de premier niveau qui sera définie dans la propriété view de UIViewController (qui conservera cette vue de premier niveau) et votre UITextField, qui sera également conservé. S'il est simplement défini, le code de chargement de la nib lui attribuera un retain, sinon la propriété l'aura retenu. L'UITextField sera également une sous-vue de l'UIView de niveau supérieur, il aura donc un retain supplémentaire sur lui, étant dans le tableau des sous-vues de la vue de niveau supérieur, donc à ce stade le champ de texte a été retenu deux fois.
À ce stade, si vous souhaitez remplacer le champ de texte par un programme, vous pouvez le faire. L'utilisation de la propriété rend la gestion de la mémoire plus claire ici ; il suffit de définir la propriété avec un nouveau champ de texte à libération automatique. Si vous n'aviez pas utilisé la propriété, vous devez vous rappeler de la libérer et, éventuellement, de conserver le nouveau champ. À ce stade, il est quelque peu ambigu de savoir à qui appartient ce nouveau champ de texte, car la sémantique de la gestion de la mémoire n'est pas contenue dans le paramètre.
Supposons maintenant qu'un autre contrôleur de vue soit poussé sur la pile du contrôleur UINavigation, de sorte que cette vue ne soit plus au premier plan. Dans le cas d'un avertissement de mémoire, la vue de ce contrôleur de vue hors écran sera déchargée. À ce stade, la propriété view de la UIView de niveau supérieur sera annulée, elle sera libérée et désallouée.
Parce que le champ UITextField a été défini comme une propriété qui a été conservée, le champ UITextField n'est pas désalloué, comme il l'aurait été si sa seule propriété conservée avait été celle du tableau des sous-vues de la vue de niveau supérieur.
Si, au contraire, la variable d'instance de l'UITextField n'avait pas été définie via une propriété, elle serait également présente, car le code de chargement de la plume l'aurait conservée lors de la définition de la variable d'instance.
Un point intéressant que cela met en évidence est que, puisque le UITextField est également conservé par la propriété, vous ne voudrez probablement pas le garder en cas d'avertissement de mémoire. Pour cette raison, vous devriez annuler la propriété dans la méthode -[UIViewController viewDidUnload]. Cela permettra de se débarrasser de la libération finale sur le UITextField et de le désallouer comme prévu. Si vous utilisez la propriété, vous devez vous souvenir de la libérer explicitement. Bien que ces deux actions soient fonctionnellement équivalentes, l'intention est différente.
Si, au lieu de remplacer le champ de texte, vous avez choisi de le supprimer de la vue, il se peut que vous l'ayez déjà supprimé de la hiérarchie de la vue et que vous ayez mis la propriété à nil, ou libéré le champ de texte. Bien qu'il soit possible d'écrire un programme correct dans ce cas, il est facile de commettre l'erreur de sur-libérer le champ de texte dans la méthode viewDidUnload. La libération excessive d'un objet est une erreur qui provoque un crash, mais le fait de redonner la valeur nil à une propriété qui l'est déjà ne l'est pas.
Ma description a peut-être été trop verbeuse, mais je ne voulais omettre aucun détail du scénario. En suivant simplement les directives, vous éviterez les problèmes lorsque vous rencontrerez des situations plus complexes.
Il convient en outre de noter que le comportement de la gestion de la mémoire diffère sur Mac OS X sur le bureau. Sur le bureau, la définition d'une IBOutlet sans setter ne conserve pas la variable d'instance, mais utilise à nouveau le setter s'il est disponible.