Question

Si j'ai quelque chose comme un UILabel lié à un fichier xib, dois-je le publier sur dealloc de ma vue? La raison pour laquelle je pose cette question est parce que je ne l'alloue pas, ce qui me fait penser que je n'ai pas besoin de le publier non plus. par exemple (dans l'en-tête):

IBOutlet UILabel *lblExample;

dans la mise en œuvre:

....
[lblExample setText:@"whatever"];
....

-(void)dealloc{
    [lblExample release];//?????????
}
Était-ce utile?

La solution

Si vous suivez ce qui est maintenant considéré comme la meilleure pratique, vous devriez publier les propriétés du point de vente, car vous devriez les avoir conservées dans l'accesseur d'ensemble:

@interface MyController : MySuperclass {
    Control *uiElement;
}
@property (nonatomic, retain) IBOutlet Control *uiElement;
@end


@implementation MyController

@synthesize uiElement;

- (void)dealloc {
    [uiElement release];
    [super dealloc];
}
@end

L’avantage de cette approche est qu’elle rend la sémantique de la gestion de la mémoire explicite et claire, et fonctionne de manière cohérente sur toutes les plateformes pour tous les fichiers nib .

Remarque: les commentaires suivants ne s'appliquent qu'à iOS antérieur à la version 3.0. Avec la version 3.0 et les versions ultérieures, vous devriez plutôt simplement supprimer les valeurs de propriété dans viewDidUnload.

Il convient toutefois de prendre en compte le moment où votre contrôleur peut disposer de son interface utilisateur et la recharger de manière dynamique à la demande (par exemple, si vous avez un contrôleur de vue qui charge une vue à partir d’un fichier NIB, mais à la demande, par exemple. sous pression mémoire - le libère, en espérant qu'il puisse être rechargé si la vue est nécessaire à nouveau). Dans cette situation, vous voulez vous assurer que, lorsque la vue principale est supprimée, vous renoncez également à la propriété de tous les autres points de vente afin qu'ils puissent également être désalloués. Pour UIViewController, vous pouvez résoudre ce problème en remplaçant setView: comme suit:

- (void)setView:(UIView *)newView {
    if (newView == nil) {
        self.uiElement = nil;
    }
    [super setView:aView];
}

Malheureusement, cela soulève un autre problème. Étant donné qu'UIViewController implémente actuellement sa méthode dealloc à l'aide de la méthode d'accès setView: (plutôt que de simplement publier directement la variable), self.anOutlet = nil être appelé dans dealloc ainsi qu'en réponse à un avertissement concernant la mémoire ... Cela entraînera un blocage de dealloc .

La solution consiste à s'assurer que les variables de sortie sont également définies sur nil dans dealloc :

- (void)dealloc {
    // release outlets and set variables to nil
    [anOutlet release], anOutlet = nil;
    [super dealloc];
}

Autres conseils

J'ai trouvé ce que je cherchais dans la documentation Apple. En bref, vous pouvez configurer vos objets en tant que propriétés que vous libérez et conservez (ou simplement @property, @synthesize), mais vous n’avez pas à le faire pour des choses comme UILabels:

http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/chapter_3_section_4.html#//apple_ref/doc/uid/10000051 a>

Le

[anOutlet release], anOutlet = nil;

La partie est totalement superflue si vous avez écrit setView: correctement.

Vous attribuez le libellé, en un sens, en le créant dans IB.

Ce que fait IB, c'est examiner vos IBOutlets et leur définition. Si vous avez une variable de classe pour laquelle IB doit attribuer une référence à un objet, IB enverra un message de conservation à cet objet pour vous.

Si vous utilisez des propriétés, IB utilisera la propriété. Vous devez définir la valeur et ne pas la conserver de manière explicite. Ainsi, vous devriez normalement marquer les propriétés IBOutlet comme étant retenue:

@property (nonatomic, retain) UILabel *lblExample;

Ainsi, dans le cas contraire (que vous utilisiez des propriétés ou non), vous devez appeler release dans votre dealloc.

Tout IBOutlet qui est une sous-vue de la vue principale de votre Nib n'a pas besoin d'être libéré, car le message autorelease leur sera envoyé lors de la création de l'objet. Les seuls objets IBOutlet à libérer dans votre dealloc sont des objets de niveau supérieur, tels que des contrôleurs ou d'autres objets NSObject. Tout cela est mentionné dans la documentation Apple ci-dessus.

Si vous ne définissez pas IBOutlet en tant que propriété, mais simplement en tant que variable d'instance, vous devez toujours le publier. En effet, lors de l'initWithNib, la mémoire sera allouée pour tous les IBOutlets. C’est donc l’un des cas particuliers que vous devez libérer même si vous n’avez ni retenu ni alloué de mémoire dans le code.

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