2009-09-25 5 views
0

Avec une instance monTableau variable:Initialiser une variable d'instance

@interface AppController : NSObject 
{ 
    NSArray *myArray; 
} 

Parfois, je vois monTableau initialisé comme ceci:

- (void)init 
{ 
    [super init]; 
    self.myArray = [[NSArray alloc] init]; 
    return self; 
} 

et parfois je vois avec une méthode plus compliquée:

- (void)init 
{ 
    [super init]; 
    NSArray *myTempArray = [[NSArray alloc] init]; 
    self.myArray = myTempArray 
    [myTempArray release]; 
    return self; 
} 

Je sais qu'il n'y a pas de différence dans le résultat final, mais pourquoi les gens prennent-ils la peine de faire la version plus longue? ? Mon sentiment est que la version plus longue est meilleure si la variable d'instance est configurée avec @property et @synthesize (probablement parce que la variable a déjà été allouée). Est-ce une partie de la raison?

Merci.

+2

Le fait que vous ayez nommé les méthodes 'init' est totalement trompeur car aucun de ceux-ci n'est qualifié à distance pour être un ini tialiseur. – bbum

Répondre

2

Si myArray est une propriété et il est mis à retain ou copy (comme cela devrait être une propriété comme celui-ci), vous finirez par double en conservant la variable lorsque vous faites ceci:

self.myArray = [[NSArray alloc] init]; 

L'appel alloc définit le nombre de références sur 1 et l'affectation de propriété le conserve ou le copie. (Pour un objet immuable, un copy est le plus souvent juste un appel à retain, il n'y a pas besoin de copier un objet qui ne peut pas changer sa valeur) Donc, après l'affectation, l'objet a conservé le compte 2, même si vous êtes seulement tenant une référence à celui-ci. Cela va perdre de la mémoire.

j'attendre à voir soit une affectation directe à l'instance de variable

myArray = [[NSArray alloc] init]; 

ou une bonne manipulation du nombre retenir:

NSArray *newArray = [[NSArray alloc] init]; 
self.myArray = newArray; 
[newArray release]; 

Ou l'utilisation d'objets autoreleased:

self.myArray = [[[NSArray alloc] init] autorelease]; // Will be released once later 
self.myArray = [NSArray array]; // Convenience constructors return autoreleased objects 
+0

Merci pour la réponse, il a éclairci certaines choses pour moi. –

0

J'ai un sentiment que vous dire ceci:

NSArray* a = [NSArray arrayWithObjects:@"foo", @"bar", nil]; 

et ce

NSArray* a = [[NSArray alloc] initWithObjects:@"foo", @"bar", nil]; 
//... 
[a release]; 

Avec le premier style, la méthode statique effectue une alloc/init/autorelease là-dessus pour vous si vous don Je ne dois pas. Avec le second style, vous avez plus de contrôle sur la libération de la mémoire au lieu de la relâcher automatiquement lorsque vous quittez le bloc en cours.

-1

Ce code plantera votre application. La deuxième version copie uniquement le pointeur puis libère l'instance. Vous devez appeler [object retain] avant de libérer la référence.

1

Ceci est un idiome utilisé dans les mutateurs (parfois appelés "setters"), mais je pense que vous l'avez tapé légèrement faux. Habituellement, il ressemble à ceci:

-(void)setMyName:(NSString *)newName 
{ 
    [newName retain]; 
    [myName release]; 
    myName = newName; 
} 

Le nouveau nom est conservé, car cette instance devra le conserver; l'ancien nom est libéré; et finalement la variable d'instance est assignée pour pointer vers le nouveau nom.

Questions connexes