Question

Voici une pratique courante que je constate souvent (y compris à partir d'un livre très populaire pour les développeurs iPhone)

Dans le fichier .h:

@interface SomeViewController : UIViewController
{
  UIImageView *imgView;
}

Quelque part dans le fichier .m:

imgView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen]
applicationFrame]];
[imgView setImage:[UIImage imageNamed:@"someimage.png"]];
[self addSubview:imgView];
[imgView release];

Et plus tard, nous voyons ceci ...

- (void) dealloc
{
  [imgView release];
  [super dealloc];

} 

Comme imgView a une allocation et une version correspondantes, la version de imgView dans dealloc est-elle nécessaire?

Où la vue imgView conservée par l'appel addSubview est-elle comptabilisée?

Était-ce utile?

La solution

Oui, ce code a des problèmes. Il publie trop tôt imgView, ce qui pourrait provoquer des plantages dans de rares circonstances stocke un objet dans une variable d'instance sans la conserver, et la gestion de la mémoire est généralement mal gérée.

Une bonne façon de faire serait:

@interface SomeViewController : UIViewController
{
    UIImageView *imgView;
}
@property (nonatomic, retain) UIImageView *imgView;

Et dans la mise en œuvre;

@synthesize imgView;

Quelque part dans le module:

//Create a new image view object and store it in a local variable (retain count 1)
UIImageView *newImgView = [[UIImageView alloc] initWithFrame:self.view.bounds];
newImgView.image = [UIImage imageNamed:@"someimage.png"];

//Use our property to store our new image view as an instance variable,
//if an old value of imgView exists, it will be released by generated method,
//and our newImgView gets retained (retain count 2)
self.imgView = newImgView;

//Release local variable, since the new UIImageView is safely stored in the
//imgView instance variable. (retain count 1)
[newImgView release];

//Add the new imgView to main view, it's retain count will be incremented,
//and the UIImageView will remain in memory until it is released by both the
//main view and this controller. (retain count 2)
[self.view addSubview:self.imgView];

Et le dealloc reste le même:

- (void) dealloc
{
    [imgView release];
    [super dealloc];
}

Autres conseils

Le code est incorrect. Vous finirez par publier imgView après la désallocation.

Dans votre fichier .m, vous:

  1. allouer il - > tu le possèdes
  2. ajoutez-le en tant que sous-vue - > vous et UIView est le propriétaire
  3. publiez il - > vous ne le possédez pas

Ensuite, dans dealloc , vous publiez imgView même si, comme nous l'avons établi à l'étape 3 ci-dessus, vous ne le possédez pas. Lorsque vous appelez [super dealloc] , la vue publiera toutes ses sous-vues et j'imagine que vous obtiendrez une exception.

Si vous souhaitez conserver un ivar de imgView , je suggère à pas d'appeler release après l'avoir ajouté en tant que sous-vue, et de conserver votre dealloc identique. Ainsi, même si imgView est à un moment quelconque supprimé de la hiérarchie des vues, vous aurez toujours une référence valide sur celle-ci.

Le code est incorrect, vous ne devriez pas le publier dans la méthode init, juste au moment où dealloc est appelé (c'est-à-dire si vous voulez le conserver sous forme d'ivar, vous n'avez pas besoin de le faire sauf si vous avez besoin d'un pointeur sur celui-ci. ailleurs puisque addSubview: conservera la vue pour vous).

Je crois que la raison pour laquelle il ne s’écrase pas réellement est qu’il est toujours conservé par la superclasse (de l’appel à addSubview :), donc lorsqu’il est publié en dealloc, il est en fait équilibré. La vue se supprime probablement d'elle-même lorsqu'elle est désallouée immédiatement après la superposition. Ainsi, lorsque [super dealloc] est appelé, sa publication n'est pas excessive. C'est mon intuition, au bail.

La libération dans init est incorrecte.

Vous avez parlé de "pratique courante". et un livre sans nom. Je suggère de regarder les exemples canoniques d’Apple: ViewTransitions est un bon exemple pour ce cas (et 2 vues pour démarrer;)

http://developer.apple.com/iphone/library /samplecode/ViewTransitions/index.html

(Je n'ai pas assez de réputation pour ajouter un commentaire .)

@bentford: corrigez-moi si je me trompe, mais je pense que pour utiliser le séparateur synthétisé de la propriété imgView, vous devez utiliser "self.imgView":

self.imgView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen]

Si vous ne possédez pas de self. , utilisez simplement l'ivar et n'obtenez pas de rétention supplémentaire.

La réponse de base est qu'il ne devrait y avoir qu'un seul [version de imgView] dans l'exemple de code ( que ce soit après addSubview ou dans dealloc ). Cependant, je supprimerais [version imgView] de dealloc et le laisserais après addSubview .

Il y a un piège sur l'iPhone; Avec didReceiveMemoryWarning , vous pourriez avoir des objets ( y compris une vue complète ) libérés sous vous. Si vous avez un ensemble de conservation à l'échelle de l'application et que vous ne respectez pas la mémoire, vous risquez de trouver l'application en cours de suppression.

Un bon exemple est le suivant:
Si vous pensez à un ensemble imbriqué de 3 vues, Afficher 1- > Voir 2- > Voir 3. Ensuite, considérons les appels ' viewDidLoad ' et ' viewDidUnload '. Si l'utilisateur est actuellement dans 'View 3', il est possible que View1 soit déchargé, et c'est là que ça devient méchant.
 Si vous avez alloué un objet dans viewDidLoad et ne l'avez pas publié après l'avoir ajouté à la sous-vue, votre objet n'est pas publié lorsque view1 est déchargé, mais view1 l'est toujours.
  viewDidLoad sera exécuté à nouveau et votre code sera exécuté à nouveau, mais vous disposez maintenant de deux instanciations de votre objet au lieu d'une; un objet sera présent dans le pays avec la vue précédemment déchargée et le nouvel objet sera pour la vue actuellement visible. Rincez, faites mousser, répétez et votre application se bloque suite à une fuite de mémoire.

Dans cet exemple, si le bloc de code donné est volatile et a une chance d'être exécuté à nouveau ( si c'est par mémoire ou par une vue non chargée ), je supprimerais [version de imgView ]; de dealloc et laissez-le après addSubView.

Voici un lien sur les concepts de base retenue / libération: http://www.otierney.net/objective-c.html#retain

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top